anujs1.4.0發佈

通過三個月的埋頭苦幹,終於完成Fiber版的anujs。
主要特性有:react

  • 測試所有改爲jest, 遷移官方測試用例。有許多迷你React吹得怎麼天花亂墜,可是生命週期鉤子的執行順序沒法與官方保持一致,那麼就很難共享React龐大的資源。像深度使用React內部 機制的ReactRouter與antd就沒法使用。
    支持新鉤子,包括getDerivedStateFromProps,getDerivedStateFromCatch, getSnapshotBeforeUpdate,componentDidCatch。新鉤子的誕生與已有的三個componentWillXXX 鉤子的廢棄是同步進行的,你在組件裏定義了新鉤子,那舊鉤子就不會被調起。
    支持批量更新API,ReactDOM.unstable_batchedUpdates, 這本來在React15的事件回調執行setState就存在的一種優化技術。如今官方將它大衆化。
    將createClass移出核心庫,已經2018年了,應該接受es6的洗禮。
    重構錯誤邊界,只差一個用例就跑通官方測試了。
    重構受控組件,所有用例跑通。
    更新劃分目錄,源碼放在packages下,分紅core, fiber與render。core對應react.js,包括一些公用方法與內置組件(Fragment組件, Portal組件, PureComponent組件, forwardRef高階組件)。fiber就是React16的異步架構。render包含了不一樣的渲染器,dom, noop(測試用), server。職責分明,有利於後繼的調優。
    支持antd 99%組件,目前只發現transfer有點問題。

這裏着重說一下fiber版塊下的設計。
unbatch內置了一個Unbatch組件,它用來模擬React內部的unbatchedUpdates。
scheduleWork裏面有一個updateComponet方法,setState的真正實現,用於驅動某一棵樹的更新。ReactDOM.render(vdom, container, cb)也會調用它進行更新,不過在咱們container與vdom中,咱們放進了一個Unbatch組件。調用ReactDOM.render至關於調用了Unbatch組件的setState, setState有第二個可選參數cb, 也就至關於ReactDOM.render的第三個可選cb。updateComponet最裏面是scheduleWork方法,它按理是使用大名鼎鼎的requestIdleCallback,如今沒有實現,臨時糊弄一下你們。webpack

let deadline = {
   didTimeout: false,
   timeRemaining() {
      return 2;
   },
};

function requestIdleCallback(fn) {
   fn(deadline);
}
Renderer.scheduleWork = function() {
   performWork(deadline);
};

performWork的實現相似於早期的rAF動畫,發現還有任務沒完工,就繼續遞歸執行自身。git

// rAF動畫的示範代碼
var start = null;
var element = document.getElementById('SomeElementYouWantToAnimate');
element.style.position = 'absolute';

function step(timestamp) {
  if (!start) start = timestamp;
  var progress = timestamp - start;
  element.style.left = Math.min(progress / 10, 200) + 'px';
  if (progress < 2000) { //遞歸執行自身
    requestAnimationFrame(step);
  }
}

requestAnimationFrame(step)
performWork的代碼也是如此
function performWork(deadline) {
   //執行當前的全部任務,更新虛擬DOM與真實DOM
   workLoop(deadline);
   //忽略其餘往macrotasks中添加任務的代碼。。。
   //忽略其餘往macrotasks中添加任務的代碼。。。
   //忽略其餘往macrotasks中添加任務的代碼。。。
   if (macrotasks.length) {
      requestIdleCallback(performWork);
   }
}

ReactFiber至關於僞造了一個瀏覽器,所以有本身調度器,事件列隊。因而你能夠看到macrotasks,microtasks,batchedtasks, boundaries, effects等列隊。
macrotasks,宏列隊,主進程,一個頁面只有一個, ReactDOM.render就會將第一個參數丟進去。es6

  1. microtasks,微列隊,子進程,每棵虛擬DOM樹都有一個,放在根節點中。當組件執行setState後,它會找到根節點的microtasks,而後放進去。而後在下次喚起performWork時,會從全部根節點中收集它們。
  2. batchedtasks,批量處理的任務,它們不能被合併。microtasks中的任務,都是由setState產生的,咱們知道對某個組件進行屢次setState,React在一次生命週期中會執行一次更新。batchedtasks則不同,它們是延後到下次生命週期,所以不能在此次生命週期中就被執行了。
  3. boundaries,放着邊界組件,邊界組件會有很高的優先級,確保它們下次在performWork中,加入macrotasks的最前面。
  4. effects,它是commit階段執行的macrotasks 列隊。
    workLoop有兩個DFS遍歷,reconcileDFS與commitDFS。reconcileDFS負責更新虛擬DOM,commitDFS負責更新真實DOM。爲何強調使用DFS,由於這東西對咱們存取context, container很是方便。
    注意:
    anujs改動比較大,致使原先的DevTool不能用,這也是後繼的工做重點了。
    雖然此次改動這麼大,它的體積仍是至關迷你的。

與1.3x同樣,它是對IE8友好的,它全部使用的es6新特性均可以被babel polyfill及使用es3ify優雅降級。目前已經有IE8專用的腳手架可用:https://gitee.com/menhal/React_IE8_boilerplate
剩下就是須要你們同心合力發掘兼容性很好的React路由庫與UI庫。web

npm i anujs

webpack.config中如何代替原來用React編寫的項目npm

resolve: {
   alias: {
      'react': 'anujs',
      'react-dom': 'anujs',
        // 若要兼容 IE 請使用如下配置
        // 'react': 'anujs/dist/ReactIE',
        // 'react-dom': 'anujs/dist/ReactIE',
    
        // 若是引用了 prop-types 或 create-react-class
        // 須要添加以下別名
        'prop-types': 'anujs/lib/ReactPropTypes',
        'create-react-class': 'anujs/lib/createClass'
        //若是你在移動端用到了onTouchTap事件
        'react-tap-event-plugin': 'anujs/lib/injectTapEventPlugin',  
   }
},
相關文章
相關標籤/搜索