React入门系列文章:7. 事件触发与组件通讯
1. 事件触发
React采用跟原生相同名字驼峰写法
的props
来定义触发类型。
比如onclick
在React中使用onClick
来定义触发的事件。
<div
onClick={(e)=>{
console.log('onclick')
console.log(e)
}}
>点击触发事件</div>
当用户点击之后,浏览器会在控制台输出
onclick
event:{}
React为事件响应做了处理,在所有的浏览器中,event是统一的、拥有一致性。
如果你非常需要使用原生对象,那么可以通过event.nativeEvent
来访问浏览器原生的事件方法。
在React中,绑定事件有很多种方式,但是我推荐使用=>
箭头方法直接指定事件处理。这种方式集合众家所长。
2. 组件间通讯
组件通讯可以用React的方式,也可以采取Redux数据驱动通讯的方式来进行。我们来简单的讲述一下React的实现。
2.1 父向子通讯
import React from 'react'
class Subchildren extends React.Component{
render () {
return <div>{this.props.text}</div>
}
}
export default FatherChildren extends React.Component{
static state = {
count:0
}
handleAdd = () => {
this.setState({count:this.state.count++})
}
render () {
return <div>
<Subchildren text={this.state.count}/>
<button onClick={this.handleAdd}>喜加1</button>
</div>
}
}
这个时候,你点击按钮 喜加1
就会发现 子组件的内容会随着父组件中state.count
的值变化而变化。
这是一种数据流向通讯。因为只需要向子组件传递消息即可。
2.2 子向父通讯
React中并没有像Vue一样的监听子组件$on
、$emmit
的功能,但是不妨碍我们将事件传入给子组件,由子组件通过事件将信息递交回父组件。
import React from 'react'
class Subchildren extends React.Component{
render () {
return <> <div>{this.props.text}</div>
<button
onClick={()=>{
this.props.onClick(0)
}
}
>重置为0</button>
</>
}
}
export default FatherChildren extends React.Component{
static state = {
count:0
}
handleAdd = () => {
this.setState({count:this.state.count++})
}
handlePostMessage = (count) => {
this.setState({count})
}
render () {
return <div>
<Subchildren
onClick={this.handlePostMessage}
text={this.state.count}/>
<button
onClick={this.handleAdd}
>喜加1</button>
</div>
}
}
点击重置为0
子组件并没有去做重置操作,而是委托给父组件传递下来的事件进行操作。这样父组件就知道了子组件想要将数据修改为0了。
2.3 兄弟组件通讯
兄弟组件通讯其实就是:父子组件通讯+子父组件通讯的混合体。
先通过子向父通讯,父组件接收到数据之后再写入到兄弟组件上去。
import React from 'react'
class Subchildren extends React.Component{
render () {
return <> <div>{this.props.text}</div>
<button
onClick={()=>{
this.props.onClick(100)
}
}
>重置为0</button>
</>
}
}
class Subchildren2 extends React.Component{
render () {
return <> <div>{this.props.text}</div>
</>
}
}
export default FatherChildren extends React.Component{
static state = {
count:0,
count2:0
}
handleAdd = () => {
this.setState({count:this.state.count++})
}
handlePostMessage = (count) => {
this.setState({count2:count})
}
render () {
return <div>
<Subchildren
onClick={this.handlePostMessage}
text={this.state.count}/>
<Subchildren2 text={this.state.count2} />
<button
onClick={this.handleAdd}
>喜加1</button>
</div>
}
}
点击重置为0,你会发现Subchildren2
组件显示数据的值为100
。这样,兄弟组件就能相互通讯了。他们是基于父组件进行的。
2.4 跨组件通讯
2.4.1 发布订阅模式
跨组件通讯,也就是多个组件在不同的容器内组成,但是又相互有数据关系依赖这样的情况下,可以再顶层自己设计一个发布/订阅的方法。
这里不过多阐述。
2.4.2 this.context
这个方法其实就是兄弟组件通讯的原理。因为React会从root
层注册一个context
,而每个组件都会将context
注册进来。
也就是说,所有的组件全局依赖一个顶层root
的 context`。
redux
也是基于这个模式设计的。
import React from 'react'
class Subchildren extends React.Component{
render () {
return <> <div>{this.props.text}</div>
<button
onClick={()=>{
this.context.handleAdd()
}
}
>加1加1加1</button>
</>
}
}
class Subchildren2 extends React.Component{
render () {
return <> <div>{this.context.value}</div>
</>
}
}
export default FatherChildren extends React.Component{
static state = {
count:0,
count2:0
}
handleAdd = () => {
this.setState({count:this.state.count++})
}
getChildContext() {
return {
value: this.state.count,
handleAdd: this.handleAdd
}
}
handlePostMessage = (count) => {
this.setState({count2:count})
}
render () {
return <div>
<Subchildren
onClick={this.handlePostMessage}
text={this.state.count}/>
<Subchildren2 text={this.state.count2} />
<button
onClick={this.handleAdd}
>喜加1</button>
</div>
}
}
主要需要注意父组件的getChildContext
,与子组件中的this.context
。