前言
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
歡迎大家在下面留言, 討論