摘要:與繼承相比,裝飾者是一種更輕便靈活的做法。它只是一種模式,這種模式是由自身的組合性質(zhì)必然產(chǎn)生的。對(duì)比原生組件增強(qiáng)的項(xiàng)可操作所有傳入的可操作組件的生命周期可操作組件的方法獲取反向繼承返回一個(gè)組件,繼承原組件,在中調(diào)用原組件的。
導(dǎo)讀
前端發(fā)展速度非常之快,頁面和組件變得越來越復(fù)雜,如何更好的實(shí)現(xiàn)狀態(tài)邏輯復(fù)用一直都是應(yīng)用程序中重要的一部分,這直接關(guān)系著應(yīng)用程序的質(zhì)量以及維護(hù)的難易程度。
本文介紹了React采用的三種實(shí)現(xiàn)狀態(tài)邏輯復(fù)用的技術(shù),并分析了他們的實(shí)現(xiàn)原理、使用方法、實(shí)際應(yīng)用以及如何選擇使用他們。
本文略長,下面是本文的思維導(dǎo)圖,您可以從頭開始閱讀,也可以選擇感興趣的部分閱讀:
Mixin設(shè)計(jì)模式Mixin(混入)是一種通過擴(kuò)展收集功能的方式,它本質(zhì)上是將一個(gè)對(duì)象的屬性拷貝到另一個(gè)對(duì)象上面去,不過你可以拷貝任意多個(gè)對(duì)象的任意個(gè)方法到一個(gè)新對(duì)象上去,這是繼承所不能實(shí)現(xiàn)的。它的出現(xiàn)主要就是為了解決代碼復(fù)用問題。
很多開源庫提供了Mixin的實(shí)現(xiàn),如Underscore的_.extend方法、JQuery的extend方法。
使用_.extend方法實(shí)現(xiàn)代碼復(fù)用:
var LogMixin = { actionLog: function() { console.log("action..."); }, requestLog: function() { console.log("request..."); }, }; function User() { /*..*/ } function Goods() { /*..*/ } _.extend(User.prototype, LogMixin); _.extend(Goods.prototype, LogMixin); var user = new User(); var good = new Goods(); user.actionLog(); good.requestLog();
我們可以嘗試手動(dòng)寫一個(gè)簡單的Mixin方法:
function setMixin(target, mixin) { if (arguments[2]) { for (var i = 2, len = arguments.length; i < len; i++) { target.prototype[arguments[i]] = mixin.prototype[arguments[i]]; } } else { for (var methodName in mixin.prototype) { if (!Object.hasOwnProperty(target.prototype, methodName)) { target.prototype[methodName] = mixin.prototype[methodName]; } } } } setMixin(User,LogMixin,"actionLog"); setMixin(Goods,LogMixin,"requestLog");
您可以使用setMixin方法將任意對(duì)象的任意方法擴(kuò)展到目標(biāo)對(duì)象上。
React中應(yīng)用MixinReact也提供了Mixin的實(shí)現(xiàn),如果完全不同的組件有相似的功能,我們可以引入來實(shí)現(xiàn)代碼復(fù)用,當(dāng)然只有在使用createClass來創(chuàng)建React組件時(shí)才可以使用,因?yàn)樵?b>React組件的es6寫法中它已經(jīng)被廢棄掉了。
例如下面的例子,很多組件或頁面都需要記錄用戶行為,性能指標(biāo)等。如果我們?cè)诿總€(gè)組件都引入寫日志的邏輯,會(huì)產(chǎn)生大量重復(fù)代碼,通過Mixin我們可以解決這一問題:
var LogMixin = { log: function() { console.log("log"); }, componentDidMount: function() { console.log("in"); }, componentWillUnmount: function() { console.log("out"); } }; var User = React.createClass({ mixins: [LogMixin], render: function() { return (Mixin帶來的危害...) } }); var Goods = React.createClass({ mixins: [LogMixin], render: function() { return (...) } });
React官方文檔在Mixins Considered Harmful一文中提到了Mixin帶來了危害:
Mixin 可能會(huì)相互依賴,相互耦合,不利于代碼維護(hù)
不同的 Mixin 中的方法可能會(huì)相互沖突
Mixin非常多時(shí),組件是可以感知到的,甚至還要為其做相關(guān)處理,這樣會(huì)給代碼造成滾雪球式的復(fù)雜性
React現(xiàn)在已經(jīng)不再推薦使用Mixin來解決代碼復(fù)用問題,因?yàn)?b>Mixin帶來的危害比他產(chǎn)生的價(jià)值還要巨大,并且React全面推薦使用高階組件來替代它。另外,高階組件還能實(shí)現(xiàn)更多其他更強(qiáng)大的功能,在學(xué)習(xí)高階組件之前,我們先來看一個(gè)設(shè)計(jì)模式。
裝飾模式裝飾者(decorator)模式能夠在不改變對(duì)象自身的基礎(chǔ)上,在程序運(yùn)行期間給對(duì)像動(dòng)態(tài)的添加職責(zé)。與繼承相比,裝飾者是一種更輕便靈活的做法。
高階組件(HOC)高階組件可以看作React對(duì)裝飾模式的一種實(shí)現(xiàn),高階組件就是一個(gè)函數(shù),且該函數(shù)接受一個(gè)組件作為參數(shù),并返回一個(gè)新的組件。
高階組件(HOC)是React中的高級(jí)技術(shù),用來重用組件邏輯。但高階組件本身并不是React API。它只是一種模式,這種模式是由React自身的組合性質(zhì)必然產(chǎn)生的。
function visible(WrappedComponent) { return class extends Component { render() { const { visible, ...props } = this.props; if (visible === false) return null; return; } } }
上面的代碼就是一個(gè)HOC的簡單應(yīng)用,函數(shù)接收一個(gè)組件作為參數(shù),并返回一個(gè)新組件,新組建可以接收一個(gè)visible props,根據(jù)visible的值來判斷是否渲染Visible。
下面我們從以下幾方面來具體探索HOC。
HOC的實(shí)現(xiàn)方式 屬性代理函數(shù)返回一個(gè)我們自己定義的組件,然后在render中返回要包裹的組件,這樣我們就可以代理所有傳入的props,并且決定如何渲染,實(shí)際上 ,這種方式生成的高階組件就是原組件的父組件,上面的函數(shù)visible就是一個(gè)HOC屬性代理的實(shí)現(xiàn)方式。
function proxyHOC(WrappedComponent) { return class extends Component { render() { return; } } }
對(duì)比原生組件增強(qiáng)的項(xiàng):
可操作所有傳入的props
可操作組件的生命周期
可操作組件的static方法
獲取refs
反向繼承返回一個(gè)組件,繼承原組件,在render中調(diào)用原組件的render。由于繼承了原組件,能通過this訪問到原組件的生命周期、props、state、render等,相比屬性代理它能操作更多的屬性。
function inheritHOC(WrappedComponent) { return class extends WrappedComponent { render() { return super.render(); } } }
對(duì)比原生組件增強(qiáng)的項(xiàng):
可操作所有傳入的props
可操作組件的生命周期
可操作組件的static方法
獲取refs
可操作state
可以渲染劫持
HOC可以實(shí)現(xiàn)什么功能 組合渲染可使用任何其他組件和原組件進(jìn)行組合渲染,達(dá)到樣式、布局復(fù)用等效果。
通過屬性代理實(shí)現(xiàn)
function stylHOC(WrappedComponent) { return class extends Component { render() { return (); } } }{this.props.title}
通過反向繼承實(shí)現(xiàn)
function styleHOC(WrappedComponent) { return class extends WrappedComponent { render() { return條件渲染} } }{this.props.title}{super.render()}
根據(jù)特定的屬性決定原組件是否渲染
通過屬性代理實(shí)現(xiàn)
function visibleHOC(WrappedComponent) { return class extends Component { render() { if (this.props.visible === false) return null; return; } } }
通過反向繼承實(shí)現(xiàn)
function visibleHOC(WrappedComponent) { return class extends WrappedComponent { render() { if (this.props.visible === false) { return null } else { return super.render() } } } }操作props
可以對(duì)傳入組件的props進(jìn)行增加、修改、刪除或者根據(jù)特定的props進(jìn)行特殊的操作。
通過屬性代理實(shí)現(xiàn)
function proxyHOC(WrappedComponent) { return class extends Component { render() { const newProps = { ...this.props, user: "ConardLi" } return獲取refs; } } }
高階組件中可獲取原組件的ref,通過ref獲取組件實(shí)力,如下面的代碼,當(dāng)程序初始化完成后調(diào)用原組件的log方法。(不知道refs怎么用,請(qǐng)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/103383.html
摘要:返回元素的是將新的與原始元素的淺層合并后的結(jié)果。生命周期方法要如何對(duì)應(yīng)到函數(shù)組件不需要構(gòu)造函數(shù)。除此之外,可以認(rèn)為的設(shè)計(jì)在某些方面更加高效避免了需要的額外開支,像是創(chuàng)建類實(shí)例和在構(gòu)造函數(shù)中綁定事件處理器的成本。 React系列 React系列 --- 簡單模擬語法(一)React系列 --- Jsx, 合成事件與Refs(二)React系列 --- virtualdom diff算法實(shí)...
摘要:但非常不幸,并不原生支持。這個(gè)單詞相信都很熟悉,高階函數(shù)在函數(shù)式編程是一個(gè)基本概念,它描述的是這樣一種函數(shù),接受函數(shù)作為輸入,或是輸出一個(gè)函數(shù)。比如常用的工具方法都是高階函數(shù)。恰與的定義完全一致。這種不同很可能會(huì)導(dǎo)致問題的產(chǎn)生。 在 React component 構(gòu)建過程中,常常有這樣的場(chǎng)景,有一類功能要被不同的 Component 公用,然后看得到文檔經(jīng)常提到 Mixin(混入) ...
摘要:已經(jīng)被廢除,具體缺陷可以參考二為了解決的缺陷,第二種解決方案是高階組件簡稱。我們定義了父組件,存在自身的,并且將自身的通過的方式傳遞給了子組件。返回一個(gè)標(biāo)識(shí)該的變量,以及更新該的方法。 ??為了實(shí)現(xiàn)分離業(yè)務(wù)邏輯代碼,實(shí)現(xiàn)組件內(nèi)部相關(guān)業(yè)務(wù)邏輯的復(fù)用,在React的迭代中針對(duì)類組件中的代碼復(fù)用依次發(fā)布了Mixin、HOC、Render props等幾個(gè)方案。此外,針對(duì)函數(shù)組件,在Reac...
摘要:已經(jīng)被廢除,具體缺陷可以參考二為了解決的缺陷,第二種解決方案是高階組件簡稱。我們定義了父組件,存在自身的,并且將自身的通過的方式傳遞給了子組件。返回一個(gè)標(biāo)識(shí)該的變量,以及更新該的方法。 ??為了實(shí)現(xiàn)分離業(yè)務(wù)邏輯代碼,實(shí)現(xiàn)組件內(nèi)部相關(guān)業(yè)務(wù)邏輯的復(fù)用,在React的迭代中針對(duì)類組件中的代碼復(fù)用依次發(fā)布了Mixin、HOC、Render props等幾個(gè)方案。此外,針對(duì)函數(shù)組件,在Reac...
摘要:已經(jīng)被廢除,具體缺陷可以參考二為了解決的缺陷,第二種解決方案是高階組件簡稱。我們定義了父組件,存在自身的,并且將自身的通過的方式傳遞給了子組件。返回一個(gè)標(biāo)識(shí)該的變量,以及更新該的方法。 ??為了實(shí)現(xiàn)分離業(yè)務(wù)邏輯代碼,實(shí)現(xiàn)組件內(nèi)部相關(guān)業(yè)務(wù)邏輯的復(fù)用,在React的迭代中針對(duì)類組件中的代碼復(fù)用依次發(fā)布了Mixin、HOC、Render props等幾個(gè)方案。此外,針對(duì)函數(shù)組件,在Reac...
閱讀 3863·2021-08-30 09:47
閱讀 3854·2019-08-30 15:56
閱讀 734·2019-08-30 14:18
閱讀 759·2019-08-29 16:17
閱讀 2114·2019-08-29 11:07
閱讀 690·2019-08-26 13:53
閱讀 3502·2019-08-26 10:26
閱讀 2545·2019-08-23 18:30