RN知识

React-Native Render Props技术使用

2018-11-13  本文已影响81人  精神病患者link常

疑问:现在有一个组件A,具有获取点击点位置信息的功能。
现在有一个需求,有一张图片需要跟随点击点进行移动,解决办法可以把图片封装到A中;现在又有另外一个需求,有一个标签需要跟随点击点进行移动,解决办法可以把标签封装到A中;现在又又有一个需求,有一个视图需要跟随点击点进行移动。。。。。。

想到另外一个办法:组件A独立,需要跟随的组件也独立B。问题是彼此独立,但是B还在A中,需要根据A的点击事件进行刷新B......

Render Props 小技术丢丢丢登场~

Render Props 小技术:是指一种在 React 组件之间使用一个值为函数的 prop 在 React 组件间共享代码的简单技术
简单来说就是组件有一个prop,这个prop是一个函数,这个函数返回组件内部需要的子组件

render prop 的来历:我们可以提供一个带有函数 prop 的 组件,它能够动态决定什么需要渲染、怎么渲染

组件A,具有获取点击点位置信息的功能。info包含的就是位置信息
组件B,就是根据info进行位置进行刷新
在组件A内部,点击事件回调this.props.render(info)
<A render={(info)=>{
  return <B ...>
}}/>

可以类比组件内部暴露出来的方法...

<A params1={1} params2={2} params3={3} onClose={()=>{...}}/>

只不过 render 返回的是一个组件,onClose 进行的是逻辑处理。

具体代码

import React, {PureComponent} from 'react';
import {BackAndroid,
    TouchableOpacity,
    View,
    Text,
    Dimensions,
    Image
} from "react-native"

import PropTypes from 'prop-types'
import Cat from './50x75.jpg'

class Move extends PureComponent {

    constructor(props) {
        super(props)

        this.state = {
            frame: {x: 0, y:0}
        }
    }

    render() {
        return (
            <View style={{flex: 1, backgroundColor: this.props.bgColor}}
                  onStartShouldSetResponder={(evt) => true}
                  onResponderGrant={(e)=>{
                      console.log('touch view =',e.nativeEvent)
                      this.setState({
                          frame: {x: e.nativeEvent.locationX, y: e.nativeEvent.locationY}
                      })
                  }}>
                {
                    // 此处调用this.props.render,传递位置信息,返回、刷新子组件
                    this.props.render(this.state.frame)
                }
            </View>
        );
    }

}

class ImageMove extends PureComponent {

    render() {
        return (
            <Image style={{left: this.props.left,top:this.props.top}} source={Cat}/>
        );
    }
}

class TitleMove extends PureComponent {

    render() {
        return (
            <Text style={{left: this.props.left,top:this.props.top,color: 'white'}}>
                当前点击位置 x:{this.props.left}   y:{this.props.top}
            </Text>
        );
    }
}


export default class jumpTest1 extends PureComponent {

    constructor(props) {
        super(props)
    }

    render() {
        return (
           <View style={{flex: 1}}>
               <Move bgColor={'red'} render={(prop)=>{
                   // 返回子组件,并根据信息改变布局
                   return <ImageMove left={prop.x} top={prop.y} />
               }}/>

               <Move bgColor={'blue'} render={(prop)=>{
                   // 返回子组件,并根据信息改变布局
                   return <TitleMove left={prop.x} top={prop.y} />
               }}/>
           </View>
        );
    }

}
QQ20181113-111752.gif

另:可以用 A 定义一个高阶组件,这样就可以在很多组件中都是用到 A 的功能。

function hocMove(Component) {
  return class extends React.Component {
    render() {
      return (
        <A render={info=> (
          <Component {...this.props} move={info} />
        )}/>
      );
    }
  }
}

⚠️注意,在 React.PureComponent 使用Render Props

render() {
        return (
           <View style={{flex: 1}}>

               // class Mouse extends React.PureComponent
               <Move bgColor={'red'} render={(prop)=>{
                   ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
                   //在此处 避免直接使用 render={()=>{}} 
                   // 当前的render() 执行时,会产生新的 < Move render={}/>
                   // 这是因为浅 prop 比较对于新 props 总会返回 false,并且在这种情况下每一个 render 对于 render prop 将会生成一个新的值
                   return <ImageMove left={prop.x} top={prop.y} />
               }}/>

           </View>
        );
    }

so~

// 愉快使用 React.PureComponent~

this.renderImageMove = this.renderImageMove.bind(this)

renderImageMove(info){
  return <ImageMove left= {info.x} top={info.y} />
}

render() {
        return (
           <View style={{flex: 1}}>
               <Move bgColor={'red'} render={this.renderImageMove}/>
           </View>
        );
    }

更多详细信息浏览 https://react.docschina.org/docs/render-props.html

上一篇 下一篇

猜你喜欢

热点阅读