摘要:這一周連續發表了兩篇關于的文章組件復用那些事兒實現按需加載輪子應用設計之道化妙用其中涉及到組件復用輪子設計相關話題,并配合相關場景實例進行了分析。
這一周連續發表了兩篇關于 React 的文章:
組件復用那些事兒 - React 實現按需加載輪子
React 應用設計之道 - curry 化妙用
其中涉及到 React 組件復用、輪子設計相關話題,并配合相關場景實例進行了分析。這些內容都算是 React 設計模式,一提到 Design Patterns,讀者大可不必恐懼,事實上這都是 React 開發應用靈活性的體現。今天這篇文章,我們繼續通過一個場景,循序漸進,通過一步步優化設計來進行加深理解。
場景介紹屏幕左側大面積展現區塊內容,點擊 continue 按鈕,切換為下條內容信息;右側是一個導航條,指示當前區塊展示信息條目。
如果看 Gif 圖不過癮,可以到 CodeSandbox 進行在線了解。
具體代碼結構為:
class App extends Component { render() { return (); } }
Stepper 組件 "stage" prop 表示默認開始第幾個區塊,同時具用同名 "stage" 狀態。stage 在這里表示左側一個個內容區塊。
handleClick 方法對 this.stata.stage 進行切換。
class Stepper extends Component { state = { stage: this.props.stage } static defaultProps = { stage: 1 } handleClick = () => { this.setState({ stage: this.state.stage + 1 }) } render() { const { stage } = this.state; return (); } }
我們看到,Stepper 組件包含 Progress 組件(左側導航)以及 Steps 組件。
這樣的代碼運行良好,但是在復用性和靈活性上有一些問題。比如:
如果我們需要切換 Progress 和 Steps 組件(左右)展示順序怎么辦?
如果我們的 Stepper 需要承載更多的 stages 怎么辦?
如果我們需要更改某個 stage 內容怎么辦?
如果我們想要切換 stages 順序該怎么辦?
現有代碼基礎上,這些問題都可以解決。但是需要重新更改組件編寫內容。如果某天又新增或者調整了需求,組件內容同樣又需要改寫。
接下來,我們用另一種方式實現需求,使得代碼更加靈活,復用性更強。
重新設計仔細觀察 Stepper 組件:它包含了當前區塊 stage,以及一個更改 stage 的方法,渲染了兩個子組件。
我們使用 Function as Child Component 手段,將 Stepper 組件重構。(如果對 Function as Child Component 不熟悉,請參考我之前文章 組件復用那些事兒 - React 實現按需加載輪子)
如下圖:
Progress 和 Steps 組件不再直接出現在 Stepper 組件的 render 方法中。我們使用 this.props.children 對 Stepper 組件的所有子組件進行渲染。這樣 Stepper 組件渲染的內容更加靈活。
但是僅僅這樣的修改是不可能完成需求的,當用戶點擊 continue 按鈕,stage 并不會進行切換。因為 Progress 和 Steps 組件無法再通過 props 感知 stage 和 handleClick 方法。
為了解決這個問題,我們可以手動遍歷 Stepper 組件的子節點,并對相應 props 一一注入。如下代碼:
const children = React.Children.map(this.props.children, child => { return React.cloneElement(child, {stage, handleClick: this.handleClick}) })
借助 React.Children.map 進行子節點遍歷,并通過 React.cloneElement 方法對子組件進行拷貝,這個方法通過第二個參數,具有添加額外 props 的能力。Stepper 組件的 render 方法只需要具體應用:
const { stage } = this.state; const children = React.Children.map(this.props.children, child => { return React.cloneElement(child, {stage, handleClick: this.handleClick}) }) return ({children});
這樣一來,應用又一次正確運轉!
class App extends Component { render() { return (); } }
同樣的手段,我們也可以應用到 Progress 組件當中。這里不再一一展開。
使用 Static Properties值得一提的是,我們可以使用 Static Properties 增強代碼的可讀性。Static Properties 允許我們在 class 當中直接對方法進行調用。首先,我們在 Stepper 組件中創建兩個 static 方法,并賦值給 Progress 組件和 Steps 組件:
static Progress = Progress; static Steps = Steps
現在,在 App.js 中我們可以直接:
import React, { Component } from "react"; import Stepper from "./Stepper" class App extends Component { render() { return (); } } export default App;
這樣的好處體現在不用一次次地 import 進來 Progress 組件和 Steps 組件,它們都將作為 Stepper 的靜態屬性出現。我個人并不是很喜歡這種做法。
使用 React Transition Group我們使用 React Transition Group 對 Steps 組件內容添加過渡動畫。只有當 props.num 與 this.props.stage 相等時,區塊內容設置為可見:
class Steps extends Component { render() { const {stage,handleClick} = this.props const children = React.Children.map(this.props.children, child => { console.log(child.props) return ( stage === child.props.num &&{child} ) }) return (); } }{children}
我們也可以給 Steps 組件添加任意個內容:
import Stepper from "./Stepper" class App extends Component { render() { return (); } }
重新設計之后,整個應用變得更加靈活,復用性更強。我們可以指定任意個 stages,每一個 stage 文本內容也可以自定義設置,同樣 stages 排列順序等都可以隨意搭配。
重構代碼以及效果可以訪問這里查看。
思考及待續如果你覺得上述代碼完美無懈可擊,那顯然想簡單了。需求是變化多端的,如果我們想在 Steps 區塊上,加一個大標題呢?
class App extends Component { render() { return (); } } Title
如圖,
這樣一來,Stepper.Steps 組件再也不是 Stepper 組件的直接唯一子節點了,那預期之中的 props 自然又一次無法取得!
問題也不僅僅于此。筆者本人不是很喜歡類似 React.cloneElement 頂層 API,除了偏好以外,也有一個難以規避的問題:在使用 React.cloneElement 擴充 props 時,如果出現 props 命名沖突怎么辦?
比如一個 遇見了命名為 value 的 prop,后果可想而知。
那么問題來了,是否有更優雅高效的方法解決上述問題?或者,是否有更好的方式,實現更靈活的設計?
答案一定是有的,我將會留在下一篇文章進行講解。
本文源于:How To Master Advanced React Design Patterns,部分內容有改動。
廣告時間:
如果你對前端發展,尤其對 React 技術棧感興趣:我的新書中,也許有你想看到的內容。關注作者 Lucas HC,新書出版將會有送書活動。
Happy Coding!
PS: 作者?Github倉庫?和?知乎問答鏈接?歡迎各種形式交流!
我的其他幾篇關于React技術棧的文章:
從setState promise化的探討 體會React團隊設計思想
React 應用設計之道 - curry 化妙用
組件復用那些事兒 - React 實現按需加載輪子
通過實例,學習編寫 React 組件的“最佳實踐”
React 組件設計和分解思考
從 React 綁定 this,看 JS 語言發展和框架設計
做出Uber移動網頁版還不夠 極致性能打造才見真章**
React+Redux打造“NEWS EARLY”單頁應用 一個項目理解最前沿技術棧真諦
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94418.html
摘要:這一周連續發表了兩篇關于的文章組件復用那些事兒實現按需加載輪子應用設計之道化妙用其中涉及到組件復用輪子設計相關話題,并配合相關場景實例進行了分析。 showImg(https://segmentfault.com/img/remote/1460000014482098); 這一周連續發表了兩篇關于 React 的文章: 組件復用那些事兒 - React 實現按需加載輪子 React ...
摘要:自動化接入和升級方案通過命令行工具提供一鍵接入升級能力,同時集成到團隊腳手架中,大大降低了工程接入和維護的成本。原始代碼經過解析器的解析,在管道中逐一經過所有規則的檢查,最終檢測出所有不符合規范的代碼,并輸出為報告。 引言 代碼規范是軟件開發領域經久不衰的話題,幾乎所有工程師在開發過程中都會遇到,并或多或少會思考過這一問題。隨著前端應用的大型化和復雜化,越來越多的前端工程師和團隊開始重...
摘要:右側展現對應產品。我們使用命名為的對象表示過濾條件信息,如下此數據需要在組件中進行維護。因為組件的子組件和都將依賴這項數據狀態。化應用再回到之前的場景,我們設計化函數,進一步可以簡化為對于的偏應用即上面提到的相信大家已經理解了這么做的好處。 showImg(https://segmentfault.com/img/remote/1460000014458612?w=1240&h=663...
閱讀 3433·2023-04-25 18:14
閱讀 1526·2021-11-24 09:38
閱讀 3244·2021-09-22 14:59
閱讀 3060·2021-08-09 13:43
閱讀 2562·2019-08-30 15:54
閱讀 562·2019-08-30 13:06
閱讀 1540·2019-08-30 12:52
閱讀 2719·2019-08-30 11:13