React 16.4新特性發布

ziyu_chen發表於2019-03-04

前言

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的觸控事件, 使其能在多種裝置上觸發,我們無需對各種型別的事件區分對待,更高的提高了開發效率, 但是目前瀏覽器的支援條件不容樂觀

WechatIMG116.jpeg

截止目前, 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官網

深入理解React16之:(一).Fiber架構

[翻譯]整合滑鼠、觸控 和觸控筆事件的Html5 Pointer Event Api

歡迎大家在下面留言, 討論

相關文章