前言
react官方在5.24号发布了16.4的release版本, 这次更新修复了一些已知问题, 比较值得关注的是对于新的生命周期getDerivedStateFromProps的修复,同时支持了 Pointer Events, 接下来详细了解一下这次更新的内容
1.Pointer Events
Pointer Events api
Pointer Events API 是Hmtl5的事件规范之一,它主要目的是用来将鼠标(Mouse)、触摸(touch)和触控笔(pen)三种事件整合为统一的API
在web页面复用在多种设备下的情况下, Pointer Events整合了mouse, touch, pen的触摸事件, 使其能在多种设备上触发,我们无需对各种类型的事件区分对待,更高的提高了开发效率, 但是目前浏览器的支持条件不容乐观
截止目前, safari依旧是全军覆没的状态, 我们可以期待的是, 作为web api的规范, 浏览器的全面支持是不远的事,react在此时支持pointer api也显示了对此api的重视, 当然我们还有第三方的 polyfill 来保持其兼容性, 我们在下面的文章会介绍下面的表格展示了三种事件的对照
Mouse event | Touch event | Pointer event |
---|---|---|
mousedown | touchstart | pointerdown |
mouseenter | pointerenter | |
mouseleave | pointerleave | |
mousemove | touchmove | pointermove |
mouseout | pointerout | |
mouseover | pointerover | |
mouseup | touchend | pointerup |
Mouse Event 和Point Event做一个对等关系很容易,但是Touch Event就没那么乐观了。但是上面的表格只是一个粗略的对照关系,相对应的事件在具体实现和含义上并不完全相同。这意味着你不能使用同一个处理函数来处理不同类型的事件,除非你明确的知道你在干什么,因为这些事件的运作方式不同。例如touchmove 事件的目标元素是touch began 时的元素,即使move的过程中触点不在该元素区域内,touchemove的目标元素仍然不会改变;但是mousemove 和 pointermove的目标元素是位于触点下方的元素,离开该元素区域,目标元素就会改变
接下来看一段简单的示例
<html>
<script>
function over_handler(event) { }
function enter_handler(event) { }
function down_handler(event) { }
function move_handler(event) { }
function up_handler(event) { }
function cancel_handler(event) { }
function out_handler(event) { }
function leave_handler(event) { }
function gotcapture_handler(event) { }
function lostcapture_handler(event) { }
function init() {
var el=document.getElementById("target");
// Register pointer event handlers
el.onpointerover = over_handler;
el.onpointerenter = enter_handler;
el.onpointerdown = down_handler;
el.onpointermove = move_handler;
el.onpointerup = up_handler;
el.onpointercancel = cancel_handler;
el.onpointerout = out_handler;
el.onpointerleave = leave_handler;
el.gotpointercapture = gotcapture_handler;
el.lostpointercapture = lostcapture_handler;
}
</script>
<body onload="init();">
<div id="target"> Touch me ... </div>
</body>
</html>
复制代码
除此之外, 我们仍然可以使用addEventListener方法添加事件
// pointermove event handler
target.addEventListener("pointermove", function(ev) {
// Process the event
}, false);
复制代码
React pointer events
React提供了以下api来支持pointer events
- onPointerDown
- onPointerMove
- onPointerUp
- onPointerCancel
- onGotPointerCapture
- onLostPointerCapture
- onPointerEnter
- onPointerLeave
- onPointerOver
- onPointerOut
需要注意的是, 上述api只在支持pointer events的浏览器中使用, react官方推荐当你在使用这个特性的时候, 使用第三方polyfill保证其兼容性, 经过对比之后,PEP这个插件很好的支持了我们的需求
接下来看一段示例
class Index extends Component {
overHandler(event) () {}
render () {
return (
<div onPointerOver={this.overHandler.bind(this)}></div>
)
}
}
复制代码
可以看到, pointer events的用法和onClick类似的, 熟练使用react的同学上手不会有什么问题
2. getDerivedStateFromProps 修复bug
React这次更新修复了getDerivedStateFromProps这个生命周期的触发节点, 在之前, 它触发的方式和旧生命周期getDerivedStateFromProps类似, 都是在被父组件re-render的时候才会触发,并且本组件的setState的调用也不会触发 这种方式在之前同步渲染的时候是没有问题的, 但是为了支持新的还未启用的fiber异步渲染机制, 现在, getDerivedStateFromProps在组件每一次render的时候都会触发,也就是说无论是来自父组件的re-render, 还是组件自身的setState, 都会触发getDerivedStateFromProps这个生命周期。 要理解为什么react修复了这个生命周期的触发方式, 我们首先得了解react的异步渲染机制
react异步渲染
要理解react异步渲染的机制, 我们首先要说一说react之前是如何进行渲染。 在react16之前, 组件的渲染都是同步进行的, 也就是说从constructor开始到componentDidUpdate结束, react的运行都是没有中断的, 生命周期开始之后就会运行到其结束为止, 这样带来的一个缺点就是,如果组件嵌套很深, 渲染时间增长了之后, 一些重要的, 高优先级的操作就会被阻塞, 例如用户的输入等, 这样就会造成体验上的不友好。
在之后即将到来的异步渲染机制中, 会允许首先解决高优先级的运行,同时会暂停当前的渲染进程,当高优先级的进程结束之后, 再返回继续运行当前进程, 这样会大大的提高react的流畅度,给用户带来更好的体验
而这次修复getDerivedStateFromProps, 正是为了保证与即将到来的异步渲染模式的兼容。
3.其他的一些改动
-
React DOM:修复在某些情况下阻止上下文传播的错误;
-
React DOM:改进 forwardRef()和 context consumers 在组件堆栈中的显示方式;
-
React DOM:当 forwardRef()渲染函数具有 propTypes 或 defaultProps 时发出警告;
-
React Test Renderer:修复 getDerivedStateFromProps()支持以匹配新的 React DOM 行为
参考 react官网
[翻译]整合鼠标、触摸 和触控笔事件的Html5 Pointer Event Api
欢迎大家在下面留言, 讨论