React事件处理
Posted 橘猫吃不胖~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React事件处理相关的知识,希望对你有一定的参考价值。
React事件处理
1 React事件处理
React与DOM事件处理的不同之处:
(1)React事件的命名方式是小驼峰方式,DOM的命名方式是小写。例如:DOM的命名:onclick,React的命名:onClick。
(2)事件处理函数是以对象的方式赋值,而不是以字符串的方式赋值。例如:DOM以字符串方式:onclick = "handleClick()"
,React以对象方式:onClick = handleClick
。
(3)阻止默认事件的方式不同。DOM通过返回false来阻止:<a href="www.baidu.com" onclick="javascript:return false;">百度</a>
,React需要显式调用e.preventDefault来阻止。
2 React中事件处理函数
2.1 使用ES6的箭头函数
1、在render函数中使用箭头函数
示例代码:点击按钮,在终端输出0
<div id="root"></div>
<script type="text/babel">
// 获取div
let root = document.getElementById("root");
// 创建类组件
class MyComponent extends React.Component
constructor(props)
super(props);
this.state = // 定义状态机
number: 0
render()
return (
<div>
/* this指向当前组件的实例 */
<button onClick=(event) => console.log(this.state.number)>点击</button>
</div>
)
// 渲染
ReactDOM.render(<MyComponent />, root);
</script>
优点:不用在构造函数中绑定this
缺点:当函数的逻辑比较复杂时,render就显得臃肿,无法直观的看到组件的UI结构,代码可读性差
2、使用class fields语法:将箭头函数赋给类的属性
示例代码:点击按钮在终端输出click
<div id="root"></div>
<script type="text/babel">
// 获取div
let root = document.getElementById("root");
// 创建类组件
class MyComponent extends React.Component
constructor(props)
super(props);
handleClick = () =>
console.log("click");
render()
return (
<button onClick=this.handleClick>点击</button>
)
// 渲染
ReactDOM.render(<MyComponent />, root);
</script>
优点:不用在构造函数中绑定this,在render函数中调用简单
2.2 在constructor函数中bind
在构造函数中进行绑定:将事件处理函数作为类的成员函数
注意:在定义事件处理函数时,是无法识别this(即this是undefined的),必须在构造函数中绑定this
示例代码:点击按钮,在终端输出click
<div id="root"></div>
<script type="text/babel">
// 获取div
let root = document.getElementById("root");
// 创建类组件
class MyComponent extends React.Component
constructor(props)
super(props);
// 将事件响应函数绑定到当前组件的实例上
this.handleClick = this.handleClick.bind(this);
// 编写事件响应函数
handleClick()
console.log("click");
render()
return (
// this.handleClick后面不加(),否则代表不点击直接调用
<button onClick=this.handleClick>点击</button>
)
// 渲染
ReactDOM.render(<MyComponent />, root);
</script>
优点:在render函数调用时不需要重新创建事件处理函数
缺点:当事件处理很多时,构造函数就显的很繁琐
2.3 在render函数中绑定this
示例代码:点击按钮,在终端输出click
<div id="root"></div>
<script type="text/babel">
// 获取div
let root = document.getElementById("root");
// 创建类组件
class MyComponent extends React.Component
constructor(props)
super(props);
// 编写事件响应函数
handleClick()
console.log("click");
render()
return (
<button onClick=this.handleClick.bind(this)>点击</button>
)
// 渲染
ReactDOM.render(<MyComponent />, root);
</script>
优点:在调用事件处理函数时,传参比较方便
缺点:每次调用render函数时都重新绑定,导致性能下降
2.4 几种方式的比较
影响 | constroctor函数中bind | 使用class fields语法 | render中使用箭头函数 | 在render中使用bind |
---|---|---|---|---|
render时生成新函数 | 否 | 否 | 是 | 是 |
性能 | 无影响 | 无影响 | 有影响 | 有影响 |
可直接携带参数 | 否 | 否 | 是 | 是 |
简洁性 | 不好 | 好 | 好 | 好 |
3 事件处理中传参
3.1 直接传递参数
1、在构造函数中给事件处理函数绑定this,调用事件处理函数时直接传参
注:在箭头函数中调用事件处理函数时不需要绑定this
示例代码:点击张三按钮,终端输出编号1,点击李四按钮,终端输出编号2
<div id="root"></div>
<script type="text/babel">
// 获取div
let root = document.getElementById("root");
// 创建类组件
class MyComponent extends React.Component
constructor(props)
super(props);
this.state =
list: [
id: 1,
name: "张三"
,
id: 2,
name: "李四"
]
// 本例中该语句不需要,因为下面的箭头函数中已经绑定了this
// this.handleClick = this.handleClick.bind(this);
handleClick(id)
console.log("编号" + id)
render()
// 获取状态属性值
const list = this.state
return (
<div>
list.map((item) => <button onClick=() => this.handleClick(item.id) >item.name</button>)
</div>
)
// 渲染
ReactDOM.render(<MyComponent />, root);
</script>
2、在render函数中调用事件处理函数时进行this的绑定
示例代码:点击张三按钮,终端输出编号1,点击李四按钮,终端输出编号2
<div id="root"></div>
<script type="text/babel">
// 获取div
let root = document.getElementById("root");
// 创建类组件
class MyComponent extends React.Component
constructor(props)
super(props);
this.state =
list: [
id: 1,
name: "张三"
,
id: 2,
name: "李四"
]
// 本例中该语句可以没有,因为下面的handleClick()函数中没有使用到this
// this.handleClick = this.handleClick.bind(this);
handleClick(id)
console.log("编号" + id)
render()
// 获取状态属性值
const list = this.state
return (
<div>
list.map((item) => <button onClick=this.handleClick.bind(this, item.id)>item.name</button>)
</div>
)
// 渲染
ReactDOM.render(<MyComponent />, root);
</script>
3.2 使用data自定义属性
在定义UI控件时使用data自定义属性,在事件处理函数中通过“e.target.dataset.属性名
”来获取UI控件中的data属性值
示例代码:点击张三按钮,终端输出编号1,点击李四按钮,终端输出编号2
<div id="root"></div>
<script type="text/babel">
// 获取div
let root = document.getElementById("root");
// 创建类组件
class MyComponent extends React.Component
constructor(props)
super(props);
this.state =
list: [
id: 1,
name: "张三"
,
id: 2,
name: "李四"
]
handleClick(e)
// 事件处理函数,e表示触发事件的对象
console.log("编号" + e.target.dataset.count)
render()
// 获取状态属性值
const list = this.state
return (
<div>
list.map((item) => <button
onClick=this.handleClick.bind(this)
data-count=item.id // 标签的自定义属性使用“data-”开头,后面跟着自定义属性名
>item.name</button>)
</div>
)
// 渲染
ReactDOM.render(<MyComponent />, root);
</script>
4 事件流
说明:
(1)React的事件流默认是冒泡
(2)React中使用捕获方式:事件类型后面加一个后缀Capture,例如:onClickCapture
示例:冒泡方式传递
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
// 1.定义CSS样式
const style =
child:
width: '100px',
height: '100px',
backgroundColor: 'red'
,
parent:
width: '150px',
height: '150px',
backgroundColor: 'blue'
,
ancestor:
width: '200px',
height: '200px',
backgroundColor: 'green'
// 2.定义类组件
class App extends React.Component
render()
return (
<div onClick=() => console.log("ancestor") style=style.ancestor>
<div onClick=() => console.log("parent") style=style.parent>
<div onClick=(e) =>
console.log("child");
style=style.child>
</div>
</div>
</div>
)
//3.渲染
ReactDOM.render(<App />, root)
</script>
点击红色区域,按照child、parent、ancestor的顺序在终端输出。
示例:捕获方式传递
// 2.定义类组件
class App extends React.Component
render()
return (
<div onClickCapture=() => console.log("ancestor") style=style.ancestor>
<div onClickCapture=() => console.log("parent") style=style.parent>
<div onClickCapture=(e) =>
console.log("child");
style=style.child>
</div>
</div>
</div>
)
点击红色区域,按照ancestor、parent、child的顺序在终端显示。
5 事件委托
在合成事件系统中,所有事件都是绑定在document元素上,即,虽然我们在某个react元素上绑定了事件,但是,最后事件都委托给document统一触发。在合成事件中只能阻止合成事件中的事件传播。
示例:基于上一部分的案例,阻止事件冒泡
// 2.定义类组件
class App extends React.Component
render()
return (
<div onClick=(e) => console.log("ancestor") style=style.ancestor>
<div onClick=(e) => console.log("parent") style=style.parent>
<div onClick=(e) =>
console.log("child");
e.stopPropagation(); // 阻止冒泡
style=style.child>
</div>
</div>
</div>
)
点击红色区域,只输出child,成功阻止了事件冒泡。
执行流程如下:
可以看到,react 阻止的事件流,并没有阻止真正DOM元素的事件触发,当红色div元素被点击时,真正的元素还是按照冒泡的方式,层层将事件交给上级元素进行处理,最后事件传播到document,触发合成事件,在合成事件中,child触发时,e.stopPropagation();被调用,合成事件中的事件被终止。因此,合成事件中的stopPropagation无法阻止事件在真正元素上的传递,它只阻止合成事件中的事件流。相反,如果我们在红色的div上,绑定一个真正的事件,那么,合成事件则会被终止。
6 事件对象
虽然React事件是合成事件,但是在事件处理中是<
以上是关于React事件处理的主要内容,如果未能解决你的问题,请参考以下文章