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