js项目实践小知识点React篇(2)

402 阅读2分钟
一、子、父组件通信 props传递
    // 1、子组件传递父组件
    // 子组件
    this.props.callBack(param)
    // 父组件
    import Children from '..../Children'
    class Parent extends Component {
        // 父组件注册方法
        parentFunc = (param) => {} // param为子组件传递过来方法
        render() {
            return <Children callBack={this.parentFunc.bind(this)}/>
        }
    }
    // 2、父组件传递子组件
    // 父组件
    class Parent extends Component {
        // 父组件注册方法
        parentFunc = (param) => {} // param为子组件传递过来方法
        render() {
            return <Children tilte="handsome"/>
        }
    }
    // 子组件
    let title = this.props.title

React 中组件间通信的几种方式

二、withRouter处理props没有路由情况 react-router
    import { withRouter } from "react-router"
    export default withRouter() // 包裹实例化类
三、日期选择插件 react-mobile-datepicker

    import DatePicker from 'react-mobile-datepicker'
    this.state = {
        time: new Date(),
        isDatePickerOpen: false
    }
    // datePicker
    handleDatePicker = () => {}) }
    handleDatePickerCancel = () => {}
    handleDatePickerSelect = (time) => {}
    
    <DatePicker
      value={time}
      isOpen={isDatePickerOpen}
      onSelect={(time)=>this.handleDatePickerSelect(time)}
      onCancel={()=>this.handleDatePickerCancel()} />

react-mobile-datepicker

四、H5上拉加载、下拉刷新组件 dropload-gh-pages

dropload-gh-pages GitHub地址

五、ListView setState不渲染 antd-mobile
    import { PullToRefresh,ListView } from 'antd-mobile'
    this.page = 1        // 当前页
    this.dataSource = [] // 数据
    this.hasMore = true  // 是否触底
    this.state = {
      dataSourceLen:0,
      masterChooseLen:0,
      // dataSource:new ListView.DataSource({rowHasChanged: (row1, row2) => row1 !== row2,}),
      dataSource:new ListView.DataSource({rowHasChanged: (row1, row2) => true,}),
      refreshing: true,
      isLoading: true,
      useBodyScroll: true,  // 上、下拉
      height:document.documentElement.clientHeight //listview
    }
    componentDidMount(){
        let _this = this
        _this.teacherList(callBackList)  // 获取教师列表
          function callBackList(data){   // callBack
            _this.dataSource = data.list
            // 拼接status,判断点击状态
            _this.dataSource.forEach((val,key)=>{
              if (!val.status) _this.dataSource[key].status = 0
            })
            _this.setState({
              dataSourceLen:data.list.length,
              refreshing: false,
              isLoading: false,
              height: hei,
              dataSource: _this.state.dataSource.cloneWithRows(_this.dataSource)
            })
          }
    }
    
  // 下拉刷新
  onRefresh = () => {
    let _this = this
    _this.page = 1
    _this.dataSource = []
    _this.setState({refreshing: true, isLoading: true})
    _this.teacherList(callBackList)  // 获取教师列表
    function callBackList(data){     // callBack
      setTimeout(()=>{
        _this.dataSource = data.list
        _this.setState({
          dataSourceLen:_this.dataSource.length,
          refreshing: false,
          isLoading: false,
          dataSource: _this.state.dataSource.cloneWithRows(_this.dataSource)
        })
      },1000)
    }
  }
  // 上拉加载
  onEndReached = () => {
    let _this = this
    if (!_this.hasMore) return false
    _this.page++
    _this.setState({ isLoading: true })
    _this.teacherList(callBackList)  // 获取教师列表
    function callBackList(data){     // callBack
      // 拼接
      _this.dataSource = _this.dataSource.concat(data.list)
      setTimeout(()=>{
        _this.setState({
          dataSourceLen:_this.dataSource.length,
          isLoading: false,
          dataSource: _this.state.dataSource.cloneWithRows(_this.dataSource)
        })
      },1000)
    }
  }
  // 接口请求
  teacherList = (callBack) => {
    ...
    if (code===200){
      // 判断是否到底
      if (data.list.length===0){
        _this.hasMore = false
      }else{
        _this.hasMore = true
      }
      callBack(data)
    }else{
      Toast.info(info,2,null,false)
      _this.setState({refreshing: false,isLoading: false})
    }      
  }
  // render
    const {
      useBodyScroll,
      dataSource,
      isLoading,
      refreshing,
      height
    } = this.state
    
  <ListView
    key={useBodyScroll ? '0' : '1'}
    ref={el => this.lv = el}
    dataSource={dataSource}
    renderHeader={() =>()}
    renderFooter={() => ()}
    renderRow={row}
    useBodyScroll={useBodyScroll}
    style={useBodyScroll ? {} : {height: height}}
    pullToRefresh={
      <PullToRefresh
        refreshing={refreshing}
        onRefresh={this.onRefresh}/>
    }
    onEndReached={this.onEndReached}
  />
六、React与原生交互
    // 1、React调原生
    if (device==='ios') window.webkit.messageHandlers.pushControllerWithURL.postMessage(url)
    if (device==='android') window.jumpToDetails.jumpToDetails(url)
    
    // 2、原生调React
    constructor(props){
        this.initialProgress = this.initialProgress.bind(this) // 初始化
    }
    componentDidMount(){
        window.initialProgress = _this.initialProgress  // 给原生实例化回调方法
    }
    initialProgress() { this.props.callBack(0) } // 原生调取方法
    // Tips:安卓订阅方法时遇到问题,iOS对接很丝滑
七、React获取Image图片高度
    <img src={...} onLoad={e => {this.imgLoad(e)}} alt="..."/>
    imgLoad = (e)=> { let height = e.target.height }
八、JSON字符串作为 URI组件进行编码encodeURIComponent/decodeURIComponent
目的:为了在url间传递大量json数据时,数据传递不报错
    let dataSub = encodeURIComponent(JSON.stringify(this.props.collection)) //string化+url编码
    let data = JSON.parse(decodeURIComponent(data)) // url解码+json化