事件
这里的事件,指的是 React 内部封装 DOM 组件中的事件,如 onClick, onFocus等,而非我们自己通过 props 传递的属性,并在子组件中手动触发的事件
实例
import React, { Component } from 'react';
class TodoList extends Component {
render() {
return (
alert(1)
}}>add
this.handelClick3()
}}>add4
);
}
handelClick () {
console.log(1)
console.log(this)
}
// 箭头函数
handelClick2 = () => {
console.log(2)
console.log(this)
}
// 箭头函数
handelClick3 = () => {
console.log(3)
console.log(this)
}
}
export default TodoList;
react事件声明
react事件采用驼峰式命名react事件接收一个函数声明,不是函数调用的形式
//原生
//react
绑定事件
采用on+事件名的方式来绑定一个事件.
注意,这里和原生的事件是有区别的: 原生的事件全是小写onclick , React里的事件是驼峰 onClick ,React的事件并不是原生事件,而是合成事件。
事件handler的写法
直接在render里写行内的箭头函数(不推荐)在组件内使用箭头函数定义一个方法(推荐)直接在组件内定义一个非箭头函数的方法,然后在render里直接使用 onClick={this.handleClick.bind(this)} (不推荐)直接在组件内定义一个非箭头函数的方法,然后在constructor里bind(this)(推荐)
Event 对象
和普通浏览器一样,事件handler会被自动传入一个 event 对象,这个对象和普通的浏览器 event 对象所包含的方法和属性都基本一致。不同的是React中的 event 对象并不是浏览器提供的,而是它自己内部所构建的。它同样具有 event.stopPropagation 、 event.preventDefault 这种常用的方法.
this问题
实例
import React, { Component } from 'react';
class TodoList extends Component {
render() {
return (
{/* :如果逻辑过不多,此写法推荐 */}
{/* 可以直接访问this,无需手动绑定 */}
console.log(0)
console.log(this)
}}>add
{/* :此写法不推荐 */}
{/* 不可以直接访问this,需手动绑定 -- .bind(this)*/}
{/* :此写法推荐 */}
{/* 可以直接访问this,无需手动绑定,handelClick2是箭头函数,可以绑定外部this :此写法推荐 */}
{/* :此写法比较推荐,传参数很方便 */}
{/* 可以直接访问this,无需手动绑定,onClick调用的是箭头函数,可以绑定外部this */}
);
}
handelClick () {
console.log(1)
console.log(this)
}
// 箭头函数
handelClick2 = (evt) => {
console.log(2)
console.log(this)
// 打印 Event 对象
console.log(evt)
}
// 箭头函数
handelClick3 = (evt) => {
console.log(3)
// 打印 Event 对象
console.log(evt)
}
}
export default TodoList;
为什么使用bind绑定this
class组件的事件绑定this问题
1. class的方法默认不会绑定 this,如果没有绑定 this.handleClick的this 并把它传入了 onClick,当你调用这个函数的时候 this 的值为 undefined。
class A extends React.Component{
constructor(props){
super(props)
}
handleClick(){
//class的方法默认不会绑定 `this`,this的指向根据调用的方式判断
//没有绑定调用的话this为undefined
this.setState({a:1})
}
render(){
return (
)
}
}
this问题的解决方式有三种
(1)在constructor里使用bind为方法绑定this
class A extends React.Component{
constructor(props){
super(props)
this.handleClick= this.handleClick.bind(this); // 注意此处
}
handleClick(){
this.setState({a:1})
}
}
(2)在元素上绑定事件时使用箭头函数
class A extends React.Component{
constructor(props){
super(props)
}
handleClick(){
//class的方法默认不会绑定 `this`,this的指向根据调用的方式判断
//没有绑定调用的话this为undefined
this.setState({a:1})
}
render(){
//render里的this指向自身
return (
)
}
}
(3)使用箭头函数声明方法
class A extends React.Component{
constructor(props){
super(props)
}
handleClick=()=>{
//箭头函数的this由父作用域的this判断
this.setState({a:1})
}
render(){
//render里的this指向自身
return (
)
}
}
react事件传递参数
1.要在绑定事件的位置给事件传参有两种方式,
(1)通过bind,使用bind会隐式传入事件对象e,作为函数的最后一个参数。
(2)通过箭头函数,使用箭头函数需要主动传入事件对象e 。
事件说明
React 根据 W3C 规范定义了合成事件 (SyntheticEvent),我们就无需担心跨浏览器的兼容性问题 React 出于性能与事件管理方面的考量,在之前的 React 版本中 (v17 之前)
会将在 JSX 中注册的事件收集到 document 上 (即通过事件委托,在 document 上注册事件,等触发事件时,则按虚拟 DOM 树的结构进行事件触发机制去分发事件);几乎所有的事件处理,均在 document 的事件中处理
比如 onFocus 等事件不会冒泡的事件,就不做委托,直接在元素上监听一些 document 上没有的事件,也直接在元素上监听 (如:audio、video标签的事件等) 在 document 中的事件处理,会根据虚拟 DOM 树的结构完成事件函数的调用,默认是冒泡机制 (事件捕获要通过类似 onClickCapture 的方式注册)React 的事件参数,并非真实的事件参数,而是 React 合成的一个对象 (SyntheticEvent)
通过调用 e.stopPropagation() 阻止事件冒泡 (仅阻止 React 事件)通过 e.nativeEvent 可以得到真实的 DOM 事件对象 (不过很少会用到)为了提高效率,React 使用事件对象池来处理事件对象 (即事件对象会重用) 在 React 17 之后,事件委托的节点就转移到了渲染的根节点上,而且也帮我们解决了此类关于事件冒泡的问题 (本文测试用例则说明,对于使用 ReactDOM.createPortal 创建的组件,表现上略有差异)
注意点
若给真实 DOM 注册事件,并阻止冒泡,则很有可能导致 React (JSX) 中注册的相关事件无法触发若给真实 DOM 注册事件,它会先于 React 事件执行 (即通过 onClick 和 dom.addEventListener 绑定的事件,真实 DOM 事件会先执行;因为这个元素被点击时,真实 DOM 事件会很快找到,而 React 绑定的事件则需要去找到事件委托的元素,再去调用当前点击元素绑定的事件函数)过 React 事件阻止事件冒泡,无法阻止真实 DOM 事件的冒泡可以使用 e.nativeEvent.stopImmediatePropagation() 去阻止 document 上剩余的事件处理程序的运行 (当我们在使用某些第三方库,在这个库有可能使用了一些事件处理,也对 document 绑定过点击事件,如: document.addEventListener("click", handler))在事件处理程序中,不要异步使用事件对象 e;如果一定有异步使用的需求,则需要调用e.persist()函数持久化保存此事件对象 (代价自然是损耗效率的)
React 事件总结
绑定事件处理函数
1.1 鼠标类
onContextMenuonClickonDoubleClickonMouseDownonMouseUponMouseEnteronMouseLeaveonMouseMoveonMouseOutonMouseOver
1.2 拖拽事件:
onDroponDragonDragStartonDragEndonDragEnteronDragLeaveonDragOveronDragExit
1.3 触摸
触摸只会在移动设备上产生
onTouchStartonTouchEndonTouchMoveonTouchCancel
1.4 键盘
onKeyPress是onKeyDown和onKeyUp的组合
onKeyPressonKeyDownonKeyUp
剪切类
对应的是我们常常使用的复制、剪切和粘贴
onCopyonCutonPaste
表单类
onChangeonInputonSubmitonChange可以用在输入框、单选框、下拉列表里,每当内容发生变化时我们都能获得通知。
onInput使用在文字输入。
onSubmit是用在整个表单的输入提交,常用在禁止表单的默认操作。
1.7 焦点事件
onFocusonBlur
1.8 UI元素类
onScroll
滚动事件触发的时候会触发onScroll事件
1.9 滚动
onWheel
鼠标滚轮触发的事件,监听滚动幅度,滚动方位
1.10 组成事件
onCompositionEndonCompositionStartonCompositionUpdate
1.11 图片类
onLoadonError
1.12 多媒体类
onAbortonCanPlayonCanPlayThroughonDurationChangeonEmptiedonEncryptedonEndedonErroronLoadedDataonLoadedMetadataonLoadStartonPauseonPlayonPlayingonProgressonRateChangeonSeekedonSeekingonStalledonSuspendonTimeUpdateonVolumeChangeonWaiting
事件池
虚拟事件对象已经被合并。这意味着虚拟事件对象将被重新使用,而该事件回调被调用之后所有的属性将无效。这是出于性能的考虑。因此,您不能以异步的方式访问事件。
function onClick(event) {
console.log(event); // =>无效的对象
console.log(event.type); // => "click"
var eventType = event.type; // => "click"
setTimeout(function() {
console.log(event.type); // => null
console.log(eventType); // => "click"
}, 0);
this.setState({clickEvent: event}); // 不起作用.this.state.clickEvent 将只包含空值.
this.setState({eventType: event.type}); // 您依然可以导出事件属性
}
如果您想以一个异步的方式来访问事件属性,您应该对事件调用event.persist()。这将从事件池中取出合成的事件,并允许该事件的引用,使用户的代码被保留。
事件对象
事件处理器将会传入SyntheticEvent的实例,一个对浏览器本地事件的跨浏览器封装。它有和浏览器本地事件有相同的属性和方法,包括stopPropagation()和preventDefault(),但是没有浏览器兼容问题。
如果因为一些因素,需要底层的浏览器事件对象,只要使用nativeEvent属性就可以获取到它了。
对于 v0.14,在事件处理函数中返回 false 将不会阻止事件冒泡。取而代之的是在合适的应用场景下,手动调用e.stopPropagation()或者e.preventDefault()。
handleChange:function(e){
console.log(e.target.value);
}
其中target是 事件对象e 是事件对象的属性
通用属性
(以下内容括号内为类型)
bubbles (boolean) 表示事件是否冒泡cancelable(boolean) 表示事件是否可以取消currentTarget(DOMEventTarget) 与Target类似,由于事件可以冒泡,所以两者表示的内容是不同的defaultPrevented(boolean) 表示事件是否禁止了默认行为eventPhase(number) 表示事件所处的阶段isTrusted(boolean) 表示事件是否可信。所谓的可信事件表示的是用户操作的事件,不可信事件就是通过JS代码来触发的事件。nativeEvent(DOMEvent)preventDefault() (void) 对应的defaultPrevented,表示的是禁止默认行为stopPropagaTion() (void) 对应的是bubbles,表示的是shtarget(DOMEventTarget)timeStamp(number) 时间戳,也就是事件触发的事件type(string) 事件的类型
不同事件对象的特有属性
剪切事件
clipboardData(DOMDataTransfer)表示拿到的数据
键盘事件
ctrlKey(boolean) 表示是否按下ctrl键altKey(boolean) 表示是否按下alt键shiftKey(boolean) 表示是否按下shiftmetaKey(boolean) 表示的是win系统下的win键,mac系统下对应的command键getModifierState(key) (function) 表示是否按下辅助按键(辅助按键就是雷士ctrl、shift等辅助按键)可以传入按键编码来判断是否按下charCode(Number) 表示的是按键的字符编码,可以通过编码来判断按下的是什么键key(string) 字符串,按下的键keyCode(Number) 表示那些不是字符编码的按键which(Number) 表示经过通用化得charCode和keyCodelocale(String) 表示本地化得一些字符串location(number) 表示位置repeat(boolean) 表示按键是否重复
焦点事件
relatedTarget(DOMEventTarget) 相关焦点对象
鼠标事件
ctrlKey(boolean)altKey(boolean)shiftKey(boolean)metaKey(boolean)getModifierState(key) (function)button(Number)buttons(Number)clientX(Number) 原点为浏览器左上角clinetY(Number) 原点为浏览器左上角pageX(Number) 原点为HTML页面的左上角pageY(Number) 原点为HTML页面的左上角screenX(Number) 原点为显示器的左上角screenY(Number) 原点为显示器的左上角relatedTarget(DOMEventTarget)
触摸事件
为了使触摸事件生效,在渲染所有组件之前调用 React.initializeTouchEvents(true)。
ctrlKey(boolean)altKey(boolean)shiftKey(boolean)metaKey(boolean)getModifierState(key)changedTouches(DOMTouchList) 判断手势操作targetTouches(DOMTouchList) 判断手势操作touches(DOMTouchList) 判断手势操作
UI元素事件
detail(Number) 滚动的距离view(DOMAbstractView) 界面,视窗
鼠标滚动
deltaMode(Number) 可以理解为移动的单位deltaX(Number) X轴移动的相对距离固定值deltaY(Number) Y轴移动的相对距离固定值deltaZ(Number) Z轴移动的相对距离固定值
实例
滚动事件对象
var HelloDada = React.creatClass({
getInitialState:function(){
return {
backgroundColor:'#FFFFFF'
}
},
handleWheel:function(e){
var newColor = (parseInt(this.state.backgroundColor.substr(1),16)+e.deltaY*997).tiString(16);
this.setState({
backgroundColor:newColor
})
},
render:function(){
return
Dada Shuaige
}
});
ReactDOM.render(
键盘事件对象
var Dada =React.creatClass{
getInitialState:function(){
return{
password:''
}
},
handleKeyPress:function(e){
this.setState({
paddword:this.state.password+e.which
});
},
handleChange:function(e){
e.target.value='';
},
render:function(){
return
// 注意这里 onKeyPress
'display':this.state.password.indexOf('495051') >=0?'block':'none'
}}>Dada handsomeboy
}
};
ReactDOM.render(
事件与状态关联
状态不仅仅实现了组件内部结果的清晰对应,还实现了组件与用户之间的交互,使用户与组件的行为紧紧结合起来
handleChange:function(e){
this.setState({Dada:e.target.value});
}
this.setState设置状态
实例
var Dada =React.creatClass({
getInitialState:function(){
return{
x:0,
y:0
}
},
handleMouseMove:function(e){
this.setState({
x:e.clientX,
y:e.clientY
});
},
render:function(){
return
width:'200px',
height:'200px',
backgroundColor:'#999'
}}>
{this.state.x+'.'+this.state.y}
}
});
ReactDOM.render(
React绑定事件和原生绑定事件的区别
react事件和原生事件的区别是:
react中的事件是绑定到document上面 , React并不会真正的绑定事件到每一个具体《》的元素上,而是采用事件代理的模式:而原生的事件是绑定到dom上面。
相对绑定的地方来说,dom上的事件要优先于document上的事件执行,react的事件对象是合成。
参考链接:
https://blog.csdn.net/qq_40340943/article/details/107309779https://www.bbsmax.com/A/Gkz1PBOgdR/
好文链接
发表评论