React系列之一起认识Render Prop
1.mixins写过react项目的应该都碰到过,不同组件复用相同代码的问题,在react早期使用React.createClass创建组件的时代,我们经常使用的是mixins来实现代码复用。比如有个组件A,它用来实时的获取鼠标的位置。 //A组件 import React from 'react' import ReactDOM from 'react-dom' const App = React.createClass({ getInitialState() { return { x: 0,y: 0 } },handleMouseMove(event) { this.setState({ x: event.clientX,y: event.clientY }) },render() { const { x,y } = this.state return ( <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}> <h1>The mouse position is ({x},{y})</h1> </div> ) } }) ReactDOM.render(<App/>,document.getElementById('app')) 如果此时有个组件B也想集成这个功能,我们可以通过mixins,代码是这样的 //B组件 import React from 'react' import ReactDOM from 'react-dom' const MouseMixin = { getInitialState() { return { x: 0,y: event.clientY }) } } const App = React.createClass({ // Use the mixin! mixins: [ MouseMixin ],document.getElementById('app')) 很容易是吧~但委屈的是react16之后就不再支持mixins了,因为es6普及了呀!
2.HOC(高阶组件)所以为了代替mixins,很多人就提出了HOC(高阶组件),代码是下面这样的。 import React from 'react' import ReactDOM from 'react-dom' const withMouse = (Component) => { return class extends React.Component { state = { x: 0,y: 0 } handleMouseMove = (event) => { this.setState({ x: event.clientX,y: event.clientY }) } render() { return ( <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}> <Component {...this.props} mouse={this.state}/> </div> ) } } } class App extends React.Component{ render() { // 代替直接处理state,我们从props里获得x,y坐标 const { x,y } = this.props.mouse return ( <div style={{ height: '100%' }}> <h1>The mouse position is ({x},{y})</h1> </div> ) } } //把App组件当做参数传到withMouse方法里面,在withMouse内部通过props获得x、y坐标值 const AppWithMouse = withMouse(App) ReactDOM.render(<AppWithMouse/>,document.getElementById('app')) 看起来很不错的样子!
我的天.....
3.Render Prop幸运女神降临! Render Prop是个值为函数的属性,通过Render Prop,组件知道什么应该被渲染 很糊涂是不是,看代码 import React from 'react' import ReactDOM from 'react-dom' import PropTypes from 'prop-types' class Mouse extends React.Component { static propTypes = { render: PropTypes.func.isRequired } state = { x: 0,y: 0 } handleMouseMove = (event) => { this.setState({ x: event.clientX,y: event.clientY }) } render() { return ( <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}> {this.props.render(this.state)} </div> ) } } const App = React.createClass({ render() { return ( <div style={{ height: '100%' }}> <Mouse render={({ x,y }) => ( <h1>The mouse position is ({x},{y})</h1> )}/> </div> ) } }) ReactDOM.render(<App/>,document.getElementById('app')) 看明白了么,这里我们通过定义一个render属性,值是个函数,描述了我们想要渲染的元素,然后在子组件里面调用该render方法,再回头看下之前的两个问题,难以溯源,现在主动权在父组件上,我要什么数据你们给我拿来就行了,你们子组件各自去实现,我只要结果不要过程,因而就不存在数据来源问题,命名空间的问题也没了。好厉害~~~。 const withMouse = (Component) => { return class extends React.Component{ render() { return <Mouse render={mouse=>( <Component {...this.props} mouse={mouse}/> )}/> } } } 据说react-router源码里面为每个组件增加路由属性就是通过该方法! 好了!大功完成了,欢迎一起讨论学习~ 个人博客地址:意卿 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |