共计 9363 个字符,预计需要花费 24 分钟才能阅读完成。
事件
这里的事件,指的是 React 外部封装 DOM 组件中的事件
,如 onClick
, onFocus
等,而非咱们本人通过 props 传递的属性,并在子组件中手动触发的事件
实例
import React, {Component} from 'react';
class TodoList extends Component {render() {
return (
<div>
<input type="text" />
<button onClick={()=>{alert(1)
}}>add</button>
<button onClick={this.handelClick}>add2</button>
<button onClick={this.handelClick2}>add3</button>
<button onClick={()=>{this.handelClick3()
}}>add4</button>
</div>
);
}
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 事件接管一个
函数申明
,不是函数调用的模式
// 原生
<div onclick="handleClick()"></div>
//react
<div onClick={this.handleClick}></div>
绑定事件
采纳 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 (
<div>
<input type="text" />
{/*:如果逻辑过不多,此写法举荐 */}
{/* 能够间接拜访 this,无需手动绑定 */}
<button onClick={()=>{console.log(0)
console.log(this)
}}>add</button>
{/*:此写法不举荐 */}
{/* 不能够间接拜访 this,需手动绑定 -- .bind(this)*/}
<button onClick={this.handelClick.bind(this)}>add2</button>
{/*:此写法举荐 */}
{/* 能够间接拜访 this,无需手动绑定,handelClick2 是箭头函数,能够绑定内部 this:此写法举荐 */}
<button onClick={this.handelClick2}>add3</button>
{/*:此写法比拟举荐,传参数很不便 */}
{/* 能够间接拜访 this,无需手动绑定,onClick 调用的是箭头函数,能够绑定内部 this */}
<button onClick={(e)=> this.handelClick3(e)}>add4</button>
</div>
);
}
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 (<div onClick={this.handleClick}></div>
)
}
}
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 (<div onClick={()=> this.handleClick()}></div>
)
}
}
(3)应用 箭头函数
申明办法
class A extends React.Component{constructor(props){super(props)
}
handleClick=()=>{
// 箭头函数的 this 由父作用域的 this 判断
this.setState({a:1})
}
render(){
//render 里的 this 指向本身
return (<div onClick={this.handleClick}></div>
)
}
}
react 事件 传递参数
1. 要在绑定事件的地位给事件传参有两种形式,
(1)通过 bind
,应用bind
会隐式传入 事件对象 e
,作为函数的最初一个参数。
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
(2)通过 箭头函数
,应用箭头函数须要 被动传入事件对象
e。
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
事件阐明
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 鼠标类
- onContextMenu
- onClick
- onDoubleClick
- onMouseDown
- onMouseUp
- onMouseEnter
- onMouseLeave
- onMouseMove
- onMouseOut
- onMouseOver
1.2 拖拽事件:
- onDrop
- onDrag
- onDragStart
- onDragEnd
- onDragEnter
- onDragLeave
- onDragOver
- onDragExit
1.3 触摸
触摸只会在挪动设施上产生
- onTouchStart
- onTouchEnd
- onTouchMove
- onTouchCancel
1.4 键盘
onKeyPress 是 onKeyDown 和 onKeyUp 的组合
- onKeyPress
- onKeyDown
- onKeyUp
剪切类
对应的是咱们经常应用的 复制
、 剪切
和粘贴
- onCopy
- onCut
- onPaste
表单类
- onChange
- onInput
- onSubmit
- onChange 能够用在输入框、单选框、下拉列表里,每当内容发生变化时咱们都能取得告诉。
onInput 应用在文字输出。
onSubmit 是用在整个表单的输出提交,罕用在禁止表单的默认操作。
1.7 焦点事件
- onFocus
- onBlur
1.8 UI 元素类
- onScroll
滚动事件触发的时候会触发 onScroll 事件
1.9 滚动
- onWheel
鼠标滚轮触发的事件,监听滚动幅度,滚动方位
1.10 组成事件
- onCompositionEnd
- onCompositionStart
- onCompositionUpdate
1.11 图片类
- onLoad
- onError
1.12 多媒体类
- onAbort
- onCanPlay
- onCanPlayThrough
- onDurationChange
- onEmptied
- onEncrypted
- onEnded
- onError
- onLoadedData
- onLoadedMetadata
- onLoadStart
- onPause
- onPlay
- onPlaying
- onProgress
- onRateChange
- onSeeked
- onSeeking
- onStalled
- onSuspend
- onTimeUpdate
- onVolumeChange
- onWaiting
事件池
虚构事件对象曾经被合并
。这意味着虚构事件对象将被从新应用,而该事件回调被调用之后所有的属性将有效。这是出于性能的思考。因而,您不能以异步的形式拜访事件。
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,示意的是 sh
- target(DOMEventTarget)
- timeStamp(number) 工夫戳,也就是事件触发的事件
- type(string) 事件的类型
不同事件对象的特有属性
剪切事件
- clipboardData(DOMDataTransfer)示意拿到的数据
键盘事件
- ctrlKey(boolean) 示意是否按下 ctrl 键
- altKey(boolean) 示意是否按下 alt 键
- shiftKey(boolean) 示意是否按下 shift
- metaKey(boolean) 示意的是 win 零碎下的 win 键,mac 零碎下对应的 command 键
- getModifierState(key) (function) 示意是否按下辅助按键(辅助按键就是雷士 ctrl、shift 等辅助按键)能够传入按键编码来判断是否按下
- charCode(Number) 示意的是按键的字符编码,能够通过编码来判断按下的是什么键
- key(string) 字符串,按下的键
- keyCode(Number) 示意那些不是字符编码的按键
- which(Number) 示意通过通用化得 charCode 和 keyCode
- locale(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 <div onWheel={this.handleWheel} style={this.state}> // 留神这里 onWheel
<p>Dada Shuaige</p>
</div>
}
});
ReactDOM.render(<HelloDada />,document.body)
键盘事件对象
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 <div>
<input onKeyPress={this.handleKeyPress} onChange={this.handleChange} /> // 留神这里 onKeyPress
<p style={{'display':this.state.password.indexOf('495051') >=0?'block':'none'
}}>Dada handsomeboy</p>
</div>
}
};
ReactDOM.render(<Dada />,document.body)
事件与状态关联
状态不仅仅实现了组件外部后果的清晰对应,还实现了组件与用户之间的交互,使用户与组件的行为紧紧联合起来
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 <div onMouseMove={this.handleMouseMove} style={{ // 留神这里 onMouseMove
width:'200px',
height:'200px',
backgroundColor:'#999'
}}>
{this.state.x+'.'+this.state.y}
</div>
}
});
ReactDOM.render(<Dada />,document.body)
React 绑定事件和原生绑定事件的区别
react 事件和原生事件的区别是:
- react 中的事件是
绑定到 document 下面
, React 并不会真正的绑定事件到每一个具体《》的元素上,而是采纳事件代理
的模式: - 而原生的事件是
绑定到 dom 下面
。
绝对绑定的中央来说,dom 上的事件要优先于 document 上的事件执行,react 的事件对象是合成。
参考链接:
- https://blog.csdn.net/qq_40340943/article/details/107309779
- https://www.bbsmax.com/A/Gkz1PBOgdR/