Maison  >  Article  >  interface Web  >  Comment encapsuler une liaison multi-niveaux React Native (implémentation du code)

Comment encapsuler une liaison multi-niveaux React Native (implémentation du code)

不言
不言original
2018-09-19 16:55:261863parcourir

Le contenu de cet article explique comment encapsuler une liaison multi-niveaux React Native (implémentation du code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Contexte

Il doit y avoir un projet récemment qui nécessite une fonction de liaison secondaire !
Au départ, je voulais le packager complètement et le mettre sur github pour gagner des étoiles, mais j'ai découvert qu'il y en avait déjà des relativement matures sur le marché. Pourquoi ne les ai-je pas recherchés avant le développement (le projet était pressé). ), j'ai fondu en larmes, maintenant qu'il a été emballé Parlons du processus

La tâche commence

1 Prototype ou dessin de conception

Avant d'emballer un composant, il faut d'abord savoir à quoi ressemble le composant, en gros. Comprendre le contour

Comment encapsuler une liaison multi-niveaux React Native (implémentation du code)

2. Concevoir la structure

Avant l'emballage. , réfléchissez-y dans votre esprit

1. Quelles fonctions ce composant doit-il remplir ?

Après avoir modifié le premier niveau, le deuxième niveau changera en conséquence. Si vous modifiez le deuxième niveau, le troisième niveau changera, et ainsi de suite. Vous pouvez spécifier les éléments qui doivent être sélectionnés, et vous pouvez modifier dynamiquement la valeur de chaque niveau. Support Load on demand

2. Quelles sont les API exposées ?

// 已封装的组件(Pickers.js)
import React, { Component } from 'react'
import Pickers from './Pickers'

class Screen extends Component {
  constructor (props) {
    super(props)
    this.state = {
      defaultIndexs: [1, 0], // 指定选择每一级的第几项,可以不填不传,默认为0(第一项)
      visible: true,  // 
      options: [ // 选项数据,label为显示的名称,children为下一级,按需加载直接改变options的值就行了
        {
          label: 'A',
          children: [
            {
              label: 'J'
            },
            {
              label: 'K'
            }
          ]
        },
        {
          label: 'B',
          children: [
            {
              label: 'X'
            },
            {
              label: 'Y'
            }
          ]
        }
      ]
    }
  }
  onChange(arr) { // 选中项改变时触发, arr为当前每一级选中项索引,如选中B和Y,此时的arr就等于[1,1]
    console.log(arr)
  }
  onOk(arr) { // 最终确认时触发,arr同上
    console.log(arr)
  }
  render() {
    return (
      <view>
        <pickers>
        </pickers>
      </view>
    )
  }
}

Au début, l'API est souvent ajoutée et modifiée pendant le processus d'encapsulation, et elle peut être adaptée de manière flexible en fonction de la situation réelle

3 .Comment permettre aux utilisateurs de l'utiliser Plus pratique ?

En utilisant les structures et styles de données actuellement populaires (vous pouvez apprendre d'autres composants), la définition du nom de l'interface est claire en un coup d'œil

4. vers plus de scénarios ?

Encapsule uniquement les fonctions, pas les affaires

3. Commencez à écrire du code

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {
  StyleSheet,
  View,
  Text,
  TouchableOpacity,
} from 'react-native'

class Pickers extends Component {
  static propTypes = {
    options: PropTypes.array,
    defaultIndexs: PropTypes.array,
    onClose: PropTypes.func,
    onChange: PropTypes.func,
    onOk: PropTypes.func,
  }

  constructor (props) {
    super(props)
    this.state = {
      options: props.options, // 选项数据
      indexs: props.defaultIndexs || [] // 当前选择的是每一级的每一项,如[1, 0],第一级的第2项,第二级的第一项
    }
    this.close = this.close.bind(this) // 指定this
    this.ok = this.ok.bind(this) // 指定this
  }
  close () { // 取消按钮事件
    this.props.onClose && this.props.onClose()
  }

  ok () { // 确认按钮事件
    this.props.onOk && this.props.onOk(this.state.indexs)
  }
  onChange () { // 选项变化的回调函数

  }
  renderItems () { // 拼装选择项组

  }

  render() {
    return (
      <view>
        <touchableopacity>
          <touchableopacity>
            <view>
              {this.renderItems()}
            </view>
            <view>
              <touchableopacity>
                <text>取消</text>
              </touchableopacity>
              <touchableopacity>
                <text>确认</text>
              </touchableopacity>
            </view>
          </touchableopacity>
        </touchableopacity>
      </view>
    )
  }
}

L'assemblage du groupe de sélection est la fonction principale et une fonction distincte est proposé ( renderItems) pour faciliter la gestion et la maintenance ultérieure

 renderItems () { // 拼装选择项组
    const items = []
    const { options = [], indexs = [] } = this.state
    const re = (arr, index) => { // index为第几级
      if (arr && arr.length > 0) {
        const childIndex = indexs[index] || 0 // 当前级指定选中第几项,默认为第一项
        items.push({
          defaultIndex: childIndex,
          values: arr //当前级的选项列表
        })
        if (arr[childIndex] && arr[childIndex].children) {
          const nextIndex = index + 1
          re(arr[childIndex].children, nextIndex)
        }
      }
    }
    re(options, 0) // re为一个递归函数
    return items.map((obj, index) => {
      return ( // PickerItem为单个选择项,list为选项列表,defaultIndex为指定选择第几项,onChange选中选项改变时回调函数,itemIndex选中的第几项,index为第几级,如(2, 1)为选中第二级的第三项
        <pickeritem> { this.onChange(itemIndex, index)}}
          />
      )
    })
  }</pickeritem>

PickerItem est un composant de sélection unique. Le Picker intégré dans React Native a des styles différents sur Android et IOS si les exigences du produit sont les mêmes. , modifiez-le simplement dans PickerItem. Il vous suffit de fournir la même interface, ce qui équivaut à ce que PickerItem soit indépendant et facile à maintenir

// 单个选项
class PickerItem extends Component {
  static propTypes = {
    list: PropTypes.array,
    onChange: PropTypes.func,
    defaultIndex: PropTypes.number,
  }

  static getDerivedStateFromProps(nextProps, prevState) { // list选项列表和defaultIndex变化之后重新渲染
    if (nextProps.list !== prevState.list ||
        nextProps.defaultIndex !== prevState.defaultIndex) {
      return {
        list: nextProps.list,
        index: nextProps.defaultIndex
      }
    }
    return null
  }

  constructor (props) {
    super(props)
    this.state = {
      list: props.list,
      index: props.defaultIndex
    }
    this.onValueChange = this.onValueChange.bind(this)
  }

  onValueChange (itemValue, itemIndex) {
    this.setState( // setState不是立即渲染
      {
        index: itemIndex
      },
      () => {
        this.props.onChange && this.props.onChange(itemIndex)
      })

  }

  render() {
    // Picker的接口直接看react native的文档https://reactnative.cn/docs/picker/
    const { list = [], index = 0 } = this.state
    const value = list[index]
    const Items = list.map((obj, index) => {
      return <picker.item></picker.item>
    })
    return (
      <picker>
        {Items}
      </picker>
    )
  }
}

Fonction de rappel onChange

 onChange (itemIndex, currentIndex) { // itemIndex选中的是第几项,currentIndex第几级发生了变化
    const indexArr = []
    const { options = [], indexs = [] } = this.state
    const re = (arr, index) => { // index为第几层,循环每一级
      if (arr && arr.length > 0) {
        let childIndex
        if (index  {
        this.props.onChange && this.props.onChange(indexArr)
      }
    )
  }

Résumé.

Il existe de nombreuses liaisons multi-niveaux matures sur le marché. Si les exigences fonctionnelles sont relativement élevées, il est recommandé d'utiliser des composants matures. De cette façon, le coût de développement est faible, la documentation est complète et elle est complète. est facile pour les autres membres de l'équipe de prendre le relais. Si vous n'utilisez que des fonctions très simples, il peut être développé rapidement. Il n'est pas nécessaire de référencer un package volumineux. Si vous souhaitez une personnalisation particulière, vous ne pouvez le développer que vous-même. Quelle que soit la situation ci-dessus, il est bon de comprendre le principe de fonctionnement à l'intérieur

Les instructions principales sont dans le code, vous pouvez également copier directement le code complet pour voir, il n'y a pas beaucoup de contenu, si vous devez obtenir la valeur correspondante, directement via Vérifiez simplement la valeur correspondante de l'index obtenu

Code complet

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {
  StyleSheet,
  View,
  Text,
  Picker,
  TouchableOpacity,
} from 'react-native'

// 单个选项
class PickerItem extends Component {
  static propTypes = {
    list: PropTypes.array,
    onChange: PropTypes.func,
    defaultIndex: PropTypes.number,
  }

  static getDerivedStateFromProps(nextProps, prevState) { // list选项列表和defaultIndex变化之后重新渲染
    if (nextProps.list !== prevState.list ||
        nextProps.defaultIndex !== prevState.defaultIndex) {
      return {
        list: nextProps.list,
        index: nextProps.defaultIndex
      }
    }
    return null
  }

  constructor (props) {
    super(props)
    this.state = {
      list: props.list,
      index: props.defaultIndex
    }
    this.onValueChange = this.onValueChange.bind(this)
  }

  onValueChange (itemValue, itemIndex) {
    this.setState( // setState不是立即渲染
      {
        index: itemIndex
      },
      () => {
        this.props.onChange && this.props.onChange(itemIndex)
      })

  }

  render() {
    // Picker的接口直接看react native的文档https://reactnative.cn/docs/picker/
    const { list = [], index = 0 } = this.state
    const value = list[index]
    const Items = list.map((obj, index) => {
      return <picker.item></picker.item>
    })
    return (
      <picker>
        {Items}
      </picker>
    )
  }
}

// Modal 安卓上无法返回
class Pickers extends Component {
  static propTypes = {
    options: PropTypes.array,
    defaultIndexs: PropTypes.array,
    onClose: PropTypes.func,
    onChange: PropTypes.func,
    onOk: PropTypes.func,
  }
  static getDerivedStateFromProps(nextProps, prevState) { // options数据选项或指定项变化时重新渲染
    if (nextProps.options !== prevState.options ||
        nextProps.defaultIndexs !== prevState.defaultIndexs) {
      return {
        options: nextProps.options,
        indexs: nextProps.defaultIndexs
      }
    }
    return null
  }
  constructor (props) {
    super(props)
    this.state = {
      options: props.options, // 选项数据
      indexs: props.defaultIndexs || [] // 当前选择的是每一级的每一项,如[1, 0],第一级的第2项,第二级的第一项
    }
    this.close = this.close.bind(this) // 指定this
    this.ok = this.ok.bind(this) // 指定this
  }
  close () { // 取消按钮事件
    this.props.onClose && this.props.onClose()
  }

  ok () { // 确认按钮事件
    this.props.onOk && this.props.onOk(this.state.indexs)
  }
  onChange (itemIndex, currentIndex) { // itemIndex选中的是第几项,currentIndex第几级发生了变化
    const indexArr = []
    const { options = [], indexs = [] } = this.state
    const re = (arr, index) => { // index为第几层,循环每一级
      if (arr && arr.length > 0) {
        let childIndex
        if (index  {
        this.props.onChange && this.props.onChange(indexArr)
      }
    )
  }
  renderItems () { // 拼装选择项组
    const items = []
    const { options = [], indexs = [] } = this.state
    const re = (arr, index) => { // index为第几级
      if (arr && arr.length > 0) {
        const childIndex = indexs[index] || 0 // 当前级指定选中第几项,默认为第一项
        items.push({
          defaultIndex: childIndex,
          values: arr //当前级的选项列表
        })
        if (arr[childIndex] && arr[childIndex].children) {
          const nextIndex = index + 1
          re(arr[childIndex].children, nextIndex)
        }
      }
    }
    re(options, 0) // re为一个递归函数
    return items.map((obj, index) => {
      return ( // PickerItem为单个选择项,list为选项列表,defaultIndex为指定选择第几项,onChange选中选项改变时回调函数
         { this.onChange(itemIndex, index)}}
          />
      )
    })
  }

  render() {
    return (
      
        
          
            
              {this.renderItems()}
            
            
              
                取消
              
              
                确认
              
            
          
        
      
    )
  }
}

const styles = StyleSheet.create({
  box: {
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    zIndex: 9999,
  },
  bg: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.4)',
    justifyContent: 'center',
    alignItems: 'center'
  },
  dialogBox: {
    width: 260,
    flexDirection: "column",
    backgroundColor: '#fff',
  },
  pickerBox: {
    flexDirection: "row",
  },
  btnBox: {
    flexDirection: "row",
    height: 45,
  },
  cancelBtn: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    borderColor: '#4A90E2',
    borderWidth: 1,
  },
  cancelBtnText: {
    fontSize: 15,
    color: '#4A90E2'
  },
  okBtn: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#4A90E2',
  },
  okBtnText: {
    fontSize: 15,
    color: '#fff'
  },
})

export default Pickers

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn