疑问:现在有一个组件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>
);
}
网友评论