摘要:精讀源碼一共行,我們分析一下其精妙的方式。更多討論討論地址是精讀新用法如果你想?yún)⑴c討論,請(qǐng)點(diǎn)擊這里,每周都有新的主題,周末或周一發(fā)布。前端精讀幫你篩選靠譜的內(nèi)容。
1 引言
很高興這一期的話題是由 epitath 的作者 grsabreu 提供的。
前端發(fā)展了 20 多年,隨著發(fā)展中國(guó)家越來(lái)越多的互聯(lián)網(wǎng)從業(yè)者涌入,現(xiàn)在前端知識(shí)玲瑯滿足,概念、庫(kù)也越來(lái)越多。雖然內(nèi)容越來(lái)越多,但作為個(gè)體的你的時(shí)間并沒(méi)有增多,如何持續(xù)學(xué)習(xí)新知識(shí),學(xué)什么將會(huì)是個(gè)大問(wèn)題。
前端精讀通過(guò)吸引優(yōu)質(zhì)的用戶,提供最前沿的話題或者設(shè)計(jì)理念,雖然每周一篇文章不足以概括這一周的所有焦點(diǎn),但可以保證你閱讀的這十幾分鐘沒(méi)有在浪費(fèi)時(shí)間,每一篇精讀都是經(jīng)過(guò)精心篩選的,我們既討論大家關(guān)注的焦點(diǎn),也能找到倉(cāng)庫(kù)角落被遺忘的珍珠。
2 概述在介紹 Epitath 之前,先介紹一下 renderProps。
renderProps 是 jsx 的一種實(shí)踐方式,renderProps 組件并不渲染 dom,但提供了持久化數(shù)據(jù)與回調(diào)函數(shù)幫助減少對(duì)當(dāng)前組件 state 的依賴。
RenderProps 的概念react-powerplug 就是一個(gè) renderProps 工具庫(kù),我們看看可以做些什么:
{({ on, toggle }) => }
Toggle 就是一個(gè) renderProps 組件,它可以幫助控制受控組件。比如僅僅利用 Toggle,我們可以大大簡(jiǎn)化 Modal 組件的使用方式:
class App extends React.Component { state = { visible: false }; showModal = () => { this.setState({ visible: true }); }; handleOk = e => { this.setState({ visible: false }); }; handleCancel = e => { this.setState({ visible: false }); }; render() { return (); } } ReactDOM.render(Some contents...
Some contents...
Some contents...
, mountNode);
這是 Modal 標(biāo)準(zhǔn)代碼,我們可以使用 Toggle 簡(jiǎn)化為:
class App extends React.Component { render() { return ({({ on, toggle }) => ( ); } } ReactDOM.render()} Some contents...
Some contents...
Some contents...
, mountNode);
省掉了 state、一堆回調(diào)函數(shù),而且代碼更簡(jiǎn)潔,更語(yǔ)義化。
renderProps 內(nèi)部管理的狀態(tài)不方便從外部獲取,因此只適合保存業(yè)務(wù)無(wú)關(guān)的數(shù)據(jù),比如 Modal 顯隱。RenderProps 嵌套問(wèn)題的解法
renderProps 雖然好用,但當(dāng)我們想組合使用時(shí),可能會(huì)遇到層層嵌套的問(wèn)題:
{counter => { {toggle => { ; }}; }}
因此 react-powerplugin 提供了 compose 函數(shù),幫助聚合 renderProps 組件:
import { compose } from "react-powerplug" const ToggleCounter = compose(使用 Epitath 解決嵌套問(wèn)題, ) {(toggle, counter) => ( )}
Epitath 提供了一種新方式解決這個(gè)嵌套的問(wèn)題:
const App = epitath(function*() { const { count } = yieldconst { on } = yield return ( ) })
renderProps 方案與 Epitath 方案,可以類(lèi)比為 回調(diào) 方案與 async/await 方案。Epitath 和 compose 都解決了 renderProps 可能帶來(lái)的嵌套問(wèn)題,而 compose 是通過(guò)將多個(gè) renderProps merge 為一個(gè),而 Epitath 的方案更接近 async/await 的思路,利用 generator 實(shí)現(xiàn)了偽同步代碼。
3 精讀Epitath 源碼一共 40 行,我們分析一下其精妙的方式。
下面是 Epitath 完整的源碼:
import React from "react"; import immutagen from "immutagen"; const compose = ({ next, value }) => next ? React.cloneElement(value, null, values => compose(next(values))) : value; export default Component => { const original = Component.prototype.render; const displayName = `EpitathContainer(${Component.displayName || "anonymous"})`; if (!original) { const generator = immutagen(Component); return Object.assign( function Epitath(props) { return compose(generator(props)); }, { displayName } ); } Component.prototype.render = function render() { // Since we are calling a new function to be called from here instead of // from a component class, we need to ensure that the render method is // invoked against `this`. We only need to do this binding and creation of // this function once, so we cache it by adding it as a property to this // new render method which avoids keeping the generator outside of this // method"s scope. if (!render.generator) { render.generator = immutagen(original.bind(this)); } return compose(render.generator(this.props)); }; return class EpitathContainer extends React.Component { static displayName = displayName; render() { returnimmutagen; } }; };
immutagen 是一個(gè) immutable generator 輔助庫(kù),每次調(diào)用 .next 都會(huì)生成一個(gè)新的引用,而不是自己發(fā)生 mutable 改變:
import immutagen from "immutagen"; const gen = immutagen(function*() { yield 1; yield 2; return 3; })(); // { value: 1, next: [function] } gen.next(); // { value: 2, next: [function] } gen.next(); // { value: 2, next: [function] } gen.next().next(); // { value: 3, next: undefined }compose
看到 compose 函數(shù)就基本明白其實(shí)現(xiàn)思路了:
const compose = ({ next, value }) => next ? React.cloneElement(value, null, values => compose(next(values))) : value;
const App = epitath(function*() { const { count } = yield; const { on } = yield ; });
通過(guò) immutagen,依次調(diào)用 next,生成新組件,且下一個(gè)組件是上一個(gè)組件的子組件,因此會(huì)產(chǎn)生下面的效果:
yield yield yield// 等價(jià)于
到此其源碼精髓已經(jīng)解析完了。
存在的問(wèn)題crimx 在討論中提到,Epitath 方案存在的最大問(wèn)題是,每次 render 都會(huì)生成全新的組件,這對(duì)內(nèi)存是一種挑戰(zhàn)。
稍微解釋一下,無(wú)論是通過(guò) 原生的 renderProps 還是 compose,同一個(gè)組件實(shí)例只生成一次,React 內(nèi)部會(huì)持久化這些組件實(shí)例。而 immutagen 在運(yùn)行時(shí)每次執(zhí)行渲染,都會(huì)生成不可變數(shù)據(jù),也就是全新的引用,這會(huì)導(dǎo)致廢棄的引用存在大量 GC 壓力,同時(shí) React 每次拿到的組件都是全新的,雖然功能相同。
4 總結(jié)epitath 巧妙的利用了 immutagen 的不可變 generator 的特性來(lái)生成組件,并且在遞歸 .next 時(shí),將順序代碼解析為嵌套代碼,有效解決了 renderProps 嵌套問(wèn)題。
喜歡 epitath 的同學(xué)趕快入手吧!同時(shí)我們也看到 generator 手動(dòng)的步驟控制帶來(lái)的威力,這是 async/await 完全無(wú)法做到的。
是否可以利用 immutagen 解決 React Context 與組件相互嵌套問(wèn)題呢?還有哪些其他前端功能可以利用 immutagen 簡(jiǎn)化的呢?歡迎加入討論。
5 更多討論討論地址是:精讀《Epitath - renderProps 新用法》 · Issue #106 · dt-fe/weekly
如果你想?yún)⑴c討論,請(qǐng)點(diǎn)擊這里,每周都有新的主題,周末或周一發(fā)布。前端精讀 - 幫你篩選靠譜的內(nèi)容。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.hztianpu.com/yun/98354.html
摘要:精讀原文介紹了學(xué)習(xí)源碼的兩個(gè)技巧,并利用實(shí)例說(shuō)明了源碼學(xué)習(xí)過(guò)程中可以學(xué)到許多周邊知識(shí),都讓我們受益匪淺。討論地址是精讀源碼學(xué)習(xí)如果你想?yún)⑴c討論,請(qǐng)點(diǎn)擊這里,每周都有新的主題,周末或周一發(fā)布。 1. 引言 javascript-knowledge-reading-source-code 這篇文章介紹了閱讀源碼的重要性,精讀系列也已有八期源碼系列文章,分別是: 精讀《Immer.js》源...
摘要:更容易將組件的與狀態(tài)分離。也就是只提供狀態(tài)處理方法,不會(huì)持久化狀態(tài)。大體思路是利用共享一份數(shù)據(jù),作為的數(shù)據(jù)源。精讀帶來(lái)的約定函數(shù)必須以命名開(kāi)頭,因?yàn)檫@樣才方便做檢查,防止用判斷包裹語(yǔ)句。前端精讀幫你篩選靠譜的內(nèi)容。 1 引言 React Hooks 是 React 16.7.0-alpha 版本推出的新特性,想嘗試的同學(xué)安裝此版本即可。 React Hooks 要解決的問(wèn)題是狀態(tài)共享,...
摘要:今天我們就來(lái)解讀一下的源碼。比較有意思,將定時(shí)器以方式提供出來(lái),并且提供了方法。實(shí)現(xiàn)方式是,在組件內(nèi)部維護(hù)一個(gè)定時(shí)器,實(shí)現(xiàn)了組件更新銷(xiāo)毀時(shí)的計(jì)時(shí)器更新銷(xiāo)毀操作,可以認(rèn)為這種定時(shí)器的生命周期綁定了組件的生命周期,不用擔(dān)心銷(xiāo)毀和更新的問(wèn)題。 1. 引言 React PowerPlug 是利用 render props 進(jìn)行更好狀態(tài)管理的工具庫(kù)。 React 項(xiàng)目中,一般一個(gè)文件就是一個(gè)類(lèi),...
摘要:可以看到,這樣不僅沒(méi)有占用組件自己的,也不需要手寫(xiě)回調(diào)函數(shù)進(jìn)行處理,這些處理都?jí)嚎s成了一行。效果通過(guò)拿到周期才執(zhí)行的回調(diào)函數(shù)。實(shí)現(xiàn)等價(jià)于的回調(diào)僅執(zhí)行一次時(shí),因此直接把回調(diào)函數(shù)拋出來(lái)即可。 1 引言 上周的 精讀《React Hooks》 已經(jīng)實(shí)現(xiàn)了對(duì) React Hooks 的基本認(rèn)知,也許你也看了 React Hooks 基本實(shí)現(xiàn)剖析(就是數(shù)組),但理解實(shí)現(xiàn)原理就可以用好了嗎?學(xué)的是...
摘要:實(shí)際上是讓組件的接收函數(shù),由函數(shù)來(lái)渲染內(nèi)容。將通用的邏輯抽象在該組件的內(nèi)部,然后依據(jù)業(yè)務(wù)邏輯來(lái)調(diào)用函數(shù)內(nèi)渲染內(nèi)容的函數(shù),從而達(dá)到重用邏輯的目的。當(dāng)然,上邊通過(guò)傳入了這屬于組件的增強(qiáng)功能。還有也提供了一種新模式來(lái)解決這個(gè)問(wèn)題。 寫(xiě)業(yè)務(wù)時(shí),我們經(jīng)常需要抽象一些使用頻率較高的邏輯,但是除了高階組件可以抽象邏輯,RenderProps也是一種比較好的方法。 RenderProps,顧名思義就是...
閱讀 2719·2021-11-24 09:38
閱讀 2697·2019-08-30 15:54
閱讀 1067·2019-08-30 15:52
閱讀 2008·2019-08-30 15:44
閱讀 2817·2019-08-30 13:48
閱讀 881·2019-08-29 16:21
閱讀 1118·2019-08-29 14:03
閱讀 2302·2019-08-28 18:15