react 讀書筆記

来源:https://www.cnblogs.com/sk-3/archive/2020/05/17/12903395.html
-Advertisement-
Play Games

"來源掘金小冊 react實戰:設計模式和最佳實踐" react設計思想 1. 屬性展開 保留當前組件需要的props,並且使其他的props傳遞下去 2. 在react中,界面完全由數據驅動 3. 在react中,一切都是組件 4. props是react組件之間通訊的基本方式 設計react組件 ...


來源掘金小冊 - react實戰:設計模式和最佳實踐

react設計思想

  1. 屬性展開 - 保留當前組件需要的props,並且使其他的props傳遞下去
  var obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
  const { a, ...other } = obj
  console.log(other)  // {b: 2, c: 3, d: 4, e: 5}
  1. 在react中,界面完全由數據驅動
  2. 在react中,一切都是組件
  3. props是react組件之間通訊的基本方式
  // 可以實現記錄用戶訪問路徑操作信息,每次進入某個頁面或者功能的時候都會訪問一個線上資源
  // a.js
  export default Beacon extends React.Component {
    componentDidMount() {
      const beacon = new Image()
      beacon.src = 'https://sxc.image/i.png'
    }
    
    render() {
      return null
    }
  }
  // b.js
  render() {
    <div>
      <Beacon/>
    </div>
  }

  // 代碼組織方式優化 - renderXXX函數訪問的是同樣的props和state,代碼耦合嚴重
  class StopWatch extends React.Component {

    renderClock() {

    }

    renderButtons() {

    }

    renderSplitTimes() {

    }
    
    render() {
      const Clock = this.renderClock()
      const Buttons = this.renderButtons()
      const SplitTimes = this.renderSplitTimes()

      return (
        <div>
          {Clock}
          {Buttons}
          {SplitTimes}
        </div>
      )
    }
  }
  // 更好的組織方式
  class StopWatch extends React.Component {
    render() {
      return (
        <div>
          <Clock />
          <Buttons />
          <SplitTimes />
        </div>
      )
    }
  }
  const Clock = (props) = {

  }
  const Buttons = (props) => {

  }
  const SplitTimes = (props) => {

  }

設計react組件原則及最佳實踐

1. 保持介面小,props數量要少
2. 根據數據邊界來劃分組件,充分利用組合
3. 把state往上層組件提取,讓下層組件只需要實現為純函數
4. 避免renderXXXX函數
5. 給回調函數類型的props加統一首碼,比如on or handle - onStart
6. 使用propTypes來定義組件的props
7. 儘量每個組件都有自己專屬的文件
8. 用解構賦值的方式獲取參數props的屬性 - const { a, b } = { a: 1, b: 2 }
9. 利用屬性初始化來定義state和成員函數 - 給預設值 const { data = [] } = this.props
  /*
    1. 儘量不要在jsx中寫內聯函數
    2. 每次渲染,都會產生新的函數對象
    3. 每次傳給組件的props(方法,數據,狀態等)都是新的,無法通過shouldComponentUpdate對props的檢查來避免重覆渲染
  */
  <Buttons
    activated={this.state.isStarted}
    onStart={() => {/* TODO */}}
    onReset={() => {/* TODO */}}
  />
  /*
    1. style屬性的使用
    2. 內聯樣式在組件每次渲染時都會創建一個新的style對象
    3. 如果樣式不發生改變,應該把style對象提取到組件之外,可以重用一個對象
  */
  // bad
  const Clock = (props) => {
    return <h1 style={color: '#ccc'}>小姐姐真好看<h1/>
  }
  // good
  const style = {
    color: '#ccc'
  }
  const Clock = (props) => {
    return <h1 style={style}>小姐姐真好看<h1/>
  }

組件樣式

1. 不同組件中相同的元素樣式相互影響,a.js與b.js中都有h1組件,樣式之間會相互影響
2. 添加styled-jsx/styled-component支持
  // a.js
  index.css
  h1: {
    color: red
  }
  <h1>a</h1>
  // b.js
  <h1>b</h1>
  
  // a.js
  .a h1: {
    color: red
  }
  <div className='a'>
    <h1>a</h1>
  <div/>
  // b.js
  <div className='b'>
    <h1>a</h1>
  <div/>

狀態組件與無狀態組件分割

1. 軟體設計原則"責任分離",就是讓一個模塊責任儘量少,每個模塊專註於一個功能,有利於代碼的維護
2. react中數據渲染頁面,UI = f(data),但是儘量把獲取和管理數據與界面渲染分開,即把獲取數據與管理數據的邏輯放在父組件,把渲染界面的邏輯放在子組件
3. A組件渲染B組件時,即使props傳入一樣,B組件也會完整走一遍渲染流程
4. 函數形式的react組件,好處是不需要管理state,占用資源少,但是函數組件無法利用shouldComponentUpdate來優化減少渲染
5. PureComponent中實現的shouldComponentUpdate會對傳入的參數進行淺比較,當傳入的props為一個對象之類的,比如由{a: 1, b: 2} => {a: 2, b: 2},可能會出現UI未更新的情況出現
6. shouldComponentUpdate函數,每次渲染render函數之前會被調用,返回true繼續渲染,返回false立刻停止,可以對深層次的數據處理
7. 在使用PureComponent時,儘量在render定義之外創建所有對象,數組和函數,並確保在各種調用間,不發生更改 - 參考table例子
8. React.memo淺比較
  export default class A extends React.Component {
    state = {
      joke: null
    }

    componentDidMount() {
      fetch(url, {header: {'Accept': 'application/json'}})
        .then(res => {
          return res.json()
        })
        .then(json => {
          this.setState({joke: json.joke})
        })
    }

    render() {
      return <B value={this.state.joke} />
    }
  }

  export default class B extends React.Component {
    render() {
      return (
        <div>
          <img src={url} />
          {this.props.value || 'loading...'}
        </div>
      )
    }
  }
  <Table
    // map每次返回一個新數組,淺比較失敗
    rows={rows.map()}
    // 枚舉對象總不相同 - 儘量不寫行內樣式
    style={{color: '#ccc'}}
    // 箭頭函數每次都會重新渲染 - 組件層級不通過箭頭函數綁定事件
    onUpdate={() => {}}
  />

高階組件

待補充...

render props模式

1. render props的形式
2. render props其實就是依賴註入
3. 如何利用render props實現共用組件之間的邏輯
4. 依賴註入:**當邏輯A依賴邏輯B時,如果讓A直接依賴B,A做不到通用。依賴註入就是把B的邏輯以函數形式傳遞給A,讓A和B之間只需要對函數介面達成一致 - 組件A和B之間,不是把B組件寫在A組件中,而是通過把B組件當參數傳到A組件當中**
  // 用戶登錄與未登錄情況下顯示不同的組件
  const Auth = (props) => {
    const userName = getUserName()
    if(userName) {
      const allProps = {userName, ...props}
      return (
        <React.Fragment>
          {props.login(allProps)}
        </React.Fragment>
      )
    } else {
      return (
        <React.Fragment>
          {props.noLogin(props)}
        </React.Fragment>
      )
    }
  }

  <Auth
    login={({userName}) => <h1>Hello {userName}</h1>}
    noLogin={() => <h1>Please login</h1>}
  />

提供者模式

1. 提供者模式,為了**解決組件間跨層級的信息傳遞**,A-B-C-D-...-X,當數據要從A傳遞到X時,通過props傳遞時,會經過B-C-D...,然而在B-C-D...中不需要使用props中的數據,而且組件在變動時,容易出現props傳遞錯誤的情況出現
2. 提供者模式,本質由2個角色組成,一個叫‘提供者’,一個叫‘消費者’,提供者(A)位於組件樹靠上的位置,消費者(X)處於靠下的位置
3. 實現方式,通過**react提供的context功能進行實現(v16.3.0+),context功能可以創造一個‘上下文’,在這個上下文之中的所有組件都可以訪問到同樣的數據**
4. 參考react-app中x2代碼

組合組件

1. 模式(Pattern) = 問題場景(Context) + 解決方法(Solution)
2. 解決的問題,**父組件想傳遞一些信息給子組件,但是通過props傳遞又很麻煩時**

組件狀態

1. UI = f(data),data = props + state,props代表外部傳進來的數據,state代表組件內部狀態
2. 什麼樣的數據可以存放在成員變數中?
3. 如果數據由外部傳入,放在props中
4. **如果是內部組件數據,這個數據的更改是否應該立刻引發一次組件的重新渲染,如果是,放在state中,不是就放在成員變數中**
5. state不會被同步修改,在react的生命周期中或者處理函數中同步調用,setState不會立即同步state和重覆渲染,但是如果setState由其他條件引發,就有可能不是這樣了 - 在生命周期中或者事件函數中調用時,react會打開一個類似標記的東西,標記打開的過程中,setState調用都是往任務隊列里放任務,當函數調用結束時,批量處理任務隊列,關閉標記
6. 函數式setState -  當setState的第一個參數為函數時,任務列表上增加的就是一個可執行的任務函數,react沒處理完一個任務,都會更新一次state,然後把新的state傳遞給這個任務函數
  // 代碼1
  class Foo extends Component {
    foo = 'foo'

    render() {
      return <div>{this.foo}</>
    }
  }
  // 代碼2
  this.state = {
    count: 0
  }

  this.setState({count: 1})
  console.log(this.state.count) // 0
  // 代碼3
  setTimeout(() => {
    this.setState({count: 2})
    console.log(this.state.count) // 2
  })
  // 代碼4 - 結果為1 三個任務都給了this.state.count一個值
  this.state = {
    count: 0
  }
  this.setState({count: this.state.count + 1})
  this.setState({count: this.state.count + 1})
  this.setState({count: this.state.count + 1})
  // 代碼5 - 函數式setState,結果為3
  // this.setState((preState, props) => ({})
  function increment(state, props) {
    return {count: state.count + 1}
  }
  this.state = {
    count: 0
  }
  this.setState(increment)
  this.setState(increment)
  this.setState(increment)

redux使用模式

1. 使用場景 - 複雜應用下的狀態維護,類似於一個全局的store,**並且store只有接受某些‘事件’(action),才可以修改store上的數據,store對這些‘事件’的響應,就是修改狀態(修改狀態的函數reducer)**
2. 事件(action) - 響應函數(reducer) -store
3. 對於某個狀態,是放在store中還是組件自身狀態中?
4. 看狀態是否會被多個react組件共用 - 不同級組件件的數據共用
5. 看這個組件被unmount之後重新被mount,之前的狀態是否需要保留 - 組件銷毀後又重新渲染,之前的輸入是否要保留
6. 代碼組織方式 - 基於角色分類(modal,services,view,action,reducer)和基於功能分類(安裝功能所在模塊分類)
7. connect函數接受兩個參數,一個mapStateToProps是把Store上的state映射為props,另一個mapDispatchToProps是把回調函數類型的props映射為派發action,connect函數調用會產生一個‘高階組件’
8. react-redux中使用了三個模式 - 提供者模式,高階組件,有狀態組件和無狀態組件
  // 代碼1
  import { createStore } from 'redux'
  import { Provider } from 'react-redux'
  import store from './store'

  const store = createStore(store)

  <Provider store={store}>
    {Provider之下的所有組件都可以connect到給定的store}
  </Provider>
  // 代碼2
  const Button = ({count, onIncrement}) => {
    return (
      <div>
        <div>{count}</div>
        <button onClick={onIncrement}>+</button>
      </div>
    )
  }
  // 代碼3
  import { connect } from 'react-redux'

  const mapStateToProps = (state) => {
    return {
      count: count + 1
    }
  }

  const mapDispatchToProps = (dispatch) => {
    onIncrement: () => dispatch({type: 'INCREMENT'})
  }

  const Counter = connect(mapStateToProps, mapDispatchToProps)(Button)

mobx使用模式

待補充...

redux與mobx模式對比

待補充...

路由 react router

1. 單頁應用 - 把URL映射到對應的頁面來處理,頁面之間切換做到局部更新
2. 動態路由 - 指的路由規則不是預先確定的,而是在渲染過程中確定的(React Router v4)
3. 靜態路由 - 路由規則是固定的

未完待續...


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一.安裝部署 "1.Zabbix部署" "2.Nessus簡介與安裝" "3.Ceph安裝" "4.Graylog 安裝" "5.Centos6.10 安裝Python 2.7.16" 更新中... 二.Linux運維 更新中... ...
  • BIOS 中英文對照表 轉載於https://www.dell.com/support/article/zh-cn/sln262122/bios-%E4%B8%AD%E8%8B%B1%E6%96%87%E5%AF%B9%E7%85%A7%E8%A1%A8?lang=zh 註意:機型不同 BIOS 版 ...
  • Redis 系列: 1. "Redis系列(一)Redis入門" 2. "Redis系列(二)Redis的8種數據類型" 3. "Redis系列(三)Redis的事務和Spring Boot整合" 4. "Redis系列(四)Redis配置文件和持久化" 5. "Redis系列(五)發佈訂閱模式、主 ...
  • 假設有一個用戶表 user,數據如下: 1、查詢表中 uid 重覆的數據 SELECT id, uid, name FROM USER WHERE uid IN (SELECT uid FROM USER GROUP BY uid HAVING COUNT(uid) > 1); 2、查詢表中重覆數據 ...
  • 在SQL Server 2017的錯誤日誌中出現"Parallel redo is started for database 'xxx' with worker pool size [2]"和“Parallel redo is shutdown for database 'xxx' with wor... ...
  • Redis 伺服器將所有的資料庫都保存在伺服器狀態redisServer結構的db數組中,db數組的每個項都是一個redisDB: struct redisServer{ //一個數組保存著伺服器中的所有資料庫 redisDb *db; //資料庫的個數 int dbnum; } dbnum:伺服器 ...
  • 一、使用碎片來進行一個最佳實踐,即我們寫一個新聞的app 1.首先先建立一個新聞類 package com.example.fragmentbestpractice; ​ public class News { private String title; private String content ...
  • 本文章將記錄Objective-C中消息傳遞和轉發機制、Method Swizzling的相關資料,如有錯誤歡迎指出~ Objective-C 本質上是一種基於 C 語言的領域特定語言。C 語言是一門靜態語言,其在編譯時決定調用哪個函數。而 Objective-C 則是一門動態語言,其在編譯時不能決 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...