react组件变外控的几种方式:eventEmitter、ref、props_this
最近很忙,搁了很久没更新了,趁着今天空闲来更新一波。
组件外控的好处是能使得React
最近解锁了组件传值的新模式,EventEmitter,fb也封装了一个fbemitter
的组件,用于fb网站间的传值。用过vue的小伙伴对event emitter肯定不陌生。这里结合react的使用来简单说明一下用法。
eventEmitter
引入
1 2
| import { EventEmitter } from 'fbemitter'; var emitter = new EventEmitter();
|
定义事件
写两个没有层级关系的组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import React, { Component } from 'react' import { EventEmitter } from 'fbemitter'
export default class EventEmitterDemo extends Component { render() { return <> <Child1 /> <Child2 /> </> } }
const emitter = new EventEmitter()
class Child1 extends Component { state = { show: '' } componentDidMount() { this.eventEmitter = emitter.addListener( 'event', (x,y)=> this.setState({ show: <>{x},{y}</> }) ) }
render(){ return <div> {this.state.show} </div> } }
|
发出并触发事件
1 2 3 4 5 6 7 8
| class Child2 extends Component { render(){ return <div> <button onClick={()=> emitter.emit('event', 12, 22)}>eventEmitter发出,见控制台</button> </div> } }
|
效果
once(eventType, callback)
只调用一次的eventEmitter,如:
1 2 3 4 5 6 7 8 9
| componentDidMount() { this.eventEmitter = emitter.once( 'event', (x,y)=> console.log(x,y) ) }
emitter.emit('event', 13);
emitter.emit('event', 12);
|
remove(eventType) 及 removeAllListeners(eventType)
删除事件,一般我们在组件卸载时应该执行remove
进行删除,而removeAllListeners
则可以一次性删除所有监听事件,如:
1 2 3 4 5 6
| componentWillUnmount(){ this.eventEmitter.remove(); this.removeAllListeners() }
|
子组件接收整个父组件this实例,达到子组件控制父组件的目的
这种原理类似HOC和装饰器函数,但比HOC写法更简洁明了,直接上代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| export class ByPropsThis extends Component { state = { count: 0}
render(){ return <> Father count: {this.state.count} <Child thisFrFather={this} /> </> } }
class Child extends Component { render(){ console.log(this.props.thisFrFather.state) return <div> <p>{this.props.count}</p> <button onClick={()=> this.props.thisFrFather.setState(({count}) => ({count: count + 1}))}> child + </button> </div> } }
|
Ref 父控制子的事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| export class ByRef extends Component { testFunc = null handleChildPlus = () => this.testFunc.plus()
render(){ return <> <button onClick={this.handleChildPlus}>plus fr father</button> {/* 整个ChildToPlus都被打上ref标记 */} <ClickToPlus ref={ ref => this.testFunc = ref } /> </> } }
class ClickToPlus extends Component { constructor(props){ super(props) this.state = {count : 0} } plus = () => this.setState(({ count }) => ({ count: count + 1 })) render() { return ( <div> <p>{this.state.count}</p> <button onClick={this.plus}>child +</button> </div> ) } }
|