摘要:會自動觸發函數內回調函數的執行。因此利用并將依賴置為使代碼在所有渲染周期內,只在初始化執行一次。同時代碼里還對等公共方法進行了包裝,讓這些回調函數中自帶效果。前端精讀幫你篩選靠譜的內容。
1. 引言
react-easy-state 是個比較有趣的庫,利用 Proxy 創建了一個非常易用的全局數據流管理方式。
import React from "react"; import { store, view } from "react-easy-state"; const counter = store({ num: 0 }); const increment = () => counter.num++; export default view(() => );
上手非常輕松,通過 store 創建一個數據對象,這個對象被任何 React 組件使用時,都會自動建立雙向綁定,任何對這個對象的修改,都會讓使用了這個對象的組件重渲染。
當然,為了實現這一點,需要對所有組件包裹一層 view。
2. 精讀這個庫利用了 nx-js/observer-util 做 Reaction 基礎 API,其他核心功能分別是 store view batch,所以我們就從這四個點進行解讀。
Reaction這個單詞名叫 “反應”,是實現雙向綁定庫的最基本功能單元。
擁有最基本的兩個單詞和一個概念:observable observe 與自動觸發執行的特性。
import { observable, observe } from "@nx-js/observer-util"; const counter = observable({ num: 0 }); const countLogger = observe(() => console.log(counter.num)); // 會自動觸發 countLogger 函數內回調函數的執行。 counter.num++;
在第 35 期精讀 精讀《dob - 框架實現》 “抽絲剝繭,實現依賴追蹤” 一節中有詳細介紹實現原理,這里就不贅述了。
有了一個具有反應特性的函數,與一個可以 “觸發反應” 的對象,那么實現雙向綁定更新 View 就不遠了。
storereact-easy-state 的 store 就是 observable(obj) 包裝一下,唯一不同是,由于支持本地數據:
import React from "react" import { view, store } from "react-easy-state" export default view(() => { const counter = store({ num: 0 }) const increment = () => counter.num++ return
所以當監測到在 React 組件內部創建 store 且是 Hooks 環境時,會返回:
return useMemo(() => observable(obj), []);
這是因為 React Hooks 場景下的 Function Component 每次渲染都會重新創建 Store,會導致死循環。因此利用 useMemo 并將依賴置為 [] 使代碼在所有渲染周期內,只在初始化執行一次。
更多 Hooks 深入解讀,可以閱讀 精讀《useEffect 完全指南》。view
根據 Function Component 與 Class Component 的不同,分別進行兩種處理,本文主要介紹對 Function Component 的處理方式,因為筆者推薦使用 Function Component 風格。
首先最外層會套上 memo,這類似 PureComponent 的效果:
return memo(/**/);
然后構造一個 forceUpdate 用來強制渲染組件:
const [, forceUpdate] = useState();
之后,只要利用 observe 包裹組件即可,需要注意兩點:
使用剛才創建的 forceUpdate 在 store 修改時調用。
observe 初始化不要執行,因為初始化組件自己會渲染一次,再渲染一次就會造成浪費。
所以作者通過 scheduler lazy 兩個參數完成了這兩件事:
const render = useMemo( () => observe(Comp, { scheduler: () => setState({}), lazy: true }), [] ); return render;
最后別忘了在組件銷毀時取消監聽:
useEffect(() => { return () => unobserve(render); }, []);batch
這也是雙向綁定數據流必須解決的經典問題,批量更新合并。
由于修改對象就觸發渲染,這個過程太自動化了,以至于我們都沒有機會告訴工具,連續的幾次修改能否合并起來只觸發一次渲染。 尤其是 For 循環修改變量時,如果不能合并更新,在某些場景下代碼幾乎是不可用的。
所以 batch 就是為解決這個問題誕生的,讓我們有機會控制合并更新的時機:
import React from "react"; import { view, store, batch } from "react-easy-state"; const user = store({ name: "Bob", age: 30 }); function mutateUser() { // this makes sure the state changes will cause maximum one re-render, // no matter where this function is getting invoked from batch(() => { user.name = "Ann"; user.age = 32; }); } export default view(() => (name: {user.name}, age: {user.age}));
react-easy-state 通過 scheduler 模塊完成 batch 功能,核心代碼只有五行:
export function batch(fn, ctx, args) { let result; unstable_batchedUpdates(() => (result = fn.apply(ctx, args))); return result; }
利用 unstable_batchedUpdates,可以保證在其內執行的函數都不會觸發更新,也就是之前創建的 forceUpdate 雖然被調用,但是失效了,等回調執行完畢時再一起批量更新。
同時代碼里還對 setTimeout setInterval addEventListener WebSocket 等公共方法進行了 batch 包裝,讓這些回調函數中自帶 batch 效果。
4. 總結好了,react-easy-state 神奇的效果解釋完了,希望大家在使用第三方庫的時候都能理解背后的原理。
PS:最后,筆者目前不推薦在 Function Component 模式下使用任何三方數據流庫,因為官方功能已經足夠好用了!討論地址是:精讀《react-easy-state》 · Issue #144 · dt-fe/weekly
如果你想參與討論,請 點擊這里,每周都有新的主題,周末或周一發布。前端精讀 - 幫你篩選靠譜的內容。
關注 前端精讀微信公眾號
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/103311.html
摘要:引言本周精讀的源碼是這個庫。這個庫的目的是為了實現的依賴注入。精讀那么開始源碼的解析,首先是整體思路的分析。討論地址是精讀源碼如果你想參與討論,請點擊這里,每周都有新的主題,周末或周一發布。前端精讀幫你篩選靠譜的內容。 1. 引言 本周精讀的源碼是 inject-instance 這個庫。 這個庫的目的是為了實現 Class 的依賴注入。 比如我們通過 inject 描述一個成員變量,...
摘要:引言是一個版語法解析器生成器,具有分詞語法樹解析的能力。實現函數用鏈表設計函數是最佳的選擇,我們要模擬調用棧了。但光標所在的位置是期望輸入點,這個輸入點也應該參與語法樹的生成,而錯誤提示不包含光標,所以我們要執行兩次。 1. 引言 syntax-parser 是一個 JS 版語法解析器生成器,具有分詞、語法樹解析的能力。 通過兩個例子介紹它的功能。 第一個例子是創建一個詞法解析器 my...
摘要:精讀源碼一共行,我們分析一下其精妙的方式。更多討論討論地址是精讀新用法如果你想參與討論,請點擊這里,每周都有新的主題,周末或周一發布。前端精讀幫你篩選靠譜的內容。 1 引言 很高興這一期的話題是由 epitath 的作者 grsabreu 提供的。 前端發展了 20 多年,隨著發展中國家越來越多的互聯網從業者涌入,現在前端知識玲瑯滿足,概念、庫也越來越多。雖然內容越來越多,但作為個體的...
摘要:今天我們就來解讀一下的源碼。比較有意思,將定時器以方式提供出來,并且提供了方法。實現方式是,在組件內部維護一個定時器,實現了組件更新銷毀時的計時器更新銷毀操作,可以認為這種定時器的生命周期綁定了組件的生命周期,不用擔心銷毀和更新的問題。 1. 引言 React PowerPlug 是利用 render props 進行更好狀態管理的工具庫。 React 項目中,一般一個文件就是一個類,...
閱讀 720·2021-10-14 09:42
閱讀 1973·2021-09-22 15:04
閱讀 1583·2019-08-30 12:44
閱讀 2144·2019-08-29 13:29
閱讀 2735·2019-08-29 12:51
閱讀 550·2019-08-26 18:18
閱讀 705·2019-08-26 13:43
閱讀 2815·2019-08-26 13:38