事件流:
在了解事件之前先来看一下什么是事件流,'流’这个名词在JS中随处可见。像DOM事件流、React中的数据流等等。其实,流就是一种有方向的数据;事件流,是页面接受事件的顺序。
DOM事件流的几个阶段:
-
事件捕获阶段
当某个事件触发时,文档根节点最先接受到事件,然后根据DOM树结构向具体绑定事件的元素传递。该阶段为父元素截获事件提供了机会。
事件传递路径为:
window —> document —> body —> button -
目标阶段
具体元素已经捕获事件,之后事件开始向根节点冒泡。 -
事件冒泡阶段
该阶段的开始即是事件的开始,根据DOM树结构由具体触发事件的元素向根节点传递。
事件传递路径:button —> body —> document —> window -
选择监听事件的阶段
使用addEventListener函数在事件流的的不同阶段监听事件,
DOM.addEventListener(‘事件名称’,handleFn,Boolean);
此处第三个参数Boolean即代表监听事件的阶段;
为true时,在在捕获阶段监听事件,执行逻辑处理;
为false时,在冒泡阶段监听事件,执行逻辑处理。
React合成事件:
- 合成事件原理
如果react事件绑定在了真实DOM节点上,一个节点同事有多个事件时,页面的响应和内存的占用会受到很大的影响。因此SyntheticEvent作为中间层出现了。
事件没有在目标对象上绑定,而是在document上监听所支持的所有事件,当事件发生并冒泡至document时,react将事件内容封装并叫由真正的处理函数运行。
React 事件绑定属性的命名采用小驼峰格式书写,事件与原生事件类似, react中是on+首字母大写的事件名,例如onClick
由于class的方法默认不会绑定this,如果没有绑定this,调用this的时候为underfined
export default class App extends React.Component {
show(){
console.log(this)
}
render (){
return <button onClick={ this.show }>点击</button>
}
解决方法:
- 在构造函数中使用bind绑定this,在构造函数 constructor 内绑定this,好处是仅需要绑定一次,避免每次渲染时都要重新绑定,函数在别处复用时也无需再次绑定
export default class App extends React.Component {
constructor(props) {
super(props);
this.show = this.show.bind(this);
}
show(){
console.log(this)
}
render() {
return <button onClick={ this.show }>点击</button>
;
}
}
- 在调用的时候使用bind绑定this,直接绑定是bind(this)来绑定,但是这样带来的问题是每一次渲染是都会重新绑定一次bind;
export default class App extends React.Component {
show(){
console.log(this);
}
render() {
return <button onClick={this.show.bind(this)}>点击</button>
}
}
- 在调用的时候使用箭头函数绑定this,箭头函数不仅是函数的’语法糖’,它还自动绑定了定义此函数作用域的this,因为我们不需要再对它们进行bind方法
export default class App extends React.Component {
show(){
console.log(this);
}
render() {
return <button onClick={()=>this.show()}>点击</button>
}
}