《React Native 精解與實戰》書籍連載「React Native 底層原理」

来源:https://www.cnblogs.com/parry/archive/2018/08/13/react_native_book_react_native_principle.html
-Advertisement-
Play Games

此文是我的出版書籍[《React Native 精解與實戰》](http://rn.parryqiu.com/)連載分享,此書由機械工業出版社出版,書中詳解了 React Native 框架底層原理、React Native 組件佈局、組件與 API 的介紹與代碼實戰,以及 React Native... ...


截圖

此文是我的出版書籍《React Native 精解與實戰》連載分享,此書由機械工業出版社出版,書中詳解了 React Native 框架底層原理、React Native 組件佈局、組件與 API 的介紹與代碼實戰,以及 React Native 與 iOS、Android 平臺的混合開發底層原理講解與代碼實戰演示,精選了大量實例代碼,方便讀者快速學習。

書籍還配套了視頻教程「80 節實戰課精通 React Native 開發」,此視頻課程建議配合書籍學習,書籍中原理性的東西講解的比較清晰,而視頻教程對於組件、API 等部分的代碼實戰開發講解比較直觀。

書籍相關所有資料請訪問:http://rn.parryqiu.com


本章將深入講解 React Native 的底層原理,萬丈高樓平地起,非常深入地理解 React Native 底層的實現,在你開發或遇到難題調試時非常有幫助。
此部分包含 React Native 的框架構成、工作原理、UI 層的渲染與重繪以及組件間通信、React Native 與各個平臺的通信實現以及 React Native 中的生命周期。
如果需要直接開始 React Native 的開發與實戰,請直接跳至第四章開始學習。

3.1 React Native 框架構成

React Native 框架內部已提供了很多的內置組件,如圖 3-1 所示。如 View、Text 等基本組件,用於一些功能佈局的 Button、Picker 等,用於列表展示的各種 List 組件和對應 iOS 平臺與 Android 平臺的特定組件、API 等。同時也提供了供編寫與原生平臺交互的介面,在後續的章節我們會進行與原生平臺的混合實戰開發實戰。
截圖
圖 3-1 React Native 框架構成

3.2 React Native 工作原理

在 React 框架介紹的章節,我們理解瞭如何將代碼渲染至虛擬 DOM 並更新到真實 DOM 的過程。在 React Native 框架中,渲染到 iOS 平臺與 Android 平臺的過程如圖 3-2 所示。
截圖
圖 3-2 React Native 渲染
在 React 框架中,JSX 源碼通過 React 框架最終渲染到了瀏覽器的真實 DOM 中,而在 React Native 框架中,JSX 源碼通過 React Native 框架編譯後,通過對應平臺的 Bridge 實現了與原生框架的通信。如果我們在程式中調用了 React Native 提供的 API,那麼 React Native 框架就通過 Bridge 調用原生框架中的方法。
因為 React Native 的底層為 React 框架,所以如果是 UI 層的變更,那麼就映射為虛擬 DOM 後進行 diff 演算法,diff 演算法計算出變動後的 JSON 映射文件,最終由 Native 層將此 JSON 文件映射渲染到原生 App 的頁面元素上,最終實現了在項目中只需要控制 state 以及 props 的變更來引起 iOS 與 Android 平臺的 UI 變更。
編寫的 React Native代碼最終會打包生成一個 main.bundle.js 文件供 App 載入,此文件可以在 App 設備本地,也可以存放於伺服器上供 App 下載更新,後續章節講解的熱更新就會涉及到 main.bundle.js 位置的設置問題。

3.3 React Native 與原生平臺通信

在與原生框架通信中,如圖 3-3 所示,React Native 採用了 JavaScriptCore 作為 JS VM,中間通過 JSON 文件與 Bridge 進行通信。而如果在使用 Chrome 瀏覽器進行調試時,那麼所有的 JavaScript 代碼都將運行在 Chrome 的 V8 引擎中,與原生代碼通過 WebSocket 進行通信。
截圖
圖 3-3 React Native 與原生平臺的通信
關於 React Native 框架與原生平臺的通信原理的詳細介紹,後續的混合開發章節將會有詳細的講解與實戰開發。

3.4 組件間通信

React Native 開發最基本的元素就是組件,React Native 與 React 一樣,也會涉及到組件之間的通信,用於數據在組件之間的傳遞,下麵列出了幾種常用的組件間通信的方式。

父子組件的通信

如同之前的章節介紹 React 組件間傳遞參數一樣,在 React Native 中,父組件向子組件傳遞值,可以通過 props 的形式。
在下例中,父組件通過調用子組件並賦值子組件的 name 為 React,子組件通過 this.props.name 獲取父組件傳遞過來的 name 的字元串值 React。
完整代碼在本書配套源碼的 03-04 文件夾。

/**
* 章節: 03-04
* 父子組件通信,在父組件中調用子組件
* FilePath: /03-04/parent-2-child.js
* @Parry
*/

<ChildComponent name='React'/>

/**
* 章節: 03-04
* 子組件實現,通過 props 獲取父頁面傳遞的值
* FilePath: /03-04/parent-2-child.js
* @Parry
*/

class ChildComponent extends Component {
    render() {
        return (
          <Text>Hello {this.props.name}!</Text>
        );
    }
}

子父組件的通信

在開發過程中,不僅有父子之間的通信,有時還會有子組件向父組件通信傳遞值的需求,比如當子組件的某個值變更後,需要通知到父組件做相應的變更與響應,那麼就會需要子父組件之間的通信。
示例代碼如下,在父組件的定義中,在調用子組件時,同樣向子組件傳遞了一個參數,不過這個參數是一個函數,此函數用於接收後續子組件向父組件傳遞過來的數據,與之前父組件向子組件傳遞數據不太一樣。
完整代碼在本書配套源碼的 03-04 文件夾。

/**
* 章節: 03-04
* 子父組件通信,父組件的實現
* FilePath: /03-04/child-2-parent.js
* @Parry
*/
import React, {Component} from 'react';
import ChildComponent from './ChildComponent'

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      name: 'React'
    }
  }

  //傳遞到子組件的參數,不過參數是一個函數。
  handleChangeName(nickName) {
    this.setState({name: nickName})
  }

  render() {
    return (
      <div>
        <p>父組件的 name:{this.state.name}</p>
        <ChildComponent
          onChange={(val) => {
          this.handleChangeName(val)
        }}/>
      </div>
    );
  }
}

export default App;

下麵為子組件的定義,子組件在頁面中定義了一個按鈕,點擊此按鈕後,調用自身的一個函數 handleChange,修改了自身 state 中的值 name 為 nickName 定義的值 Parry,那麼此子組件的頁面上的字元串將由之前的 Hello React! 變為 Hello Parry!,同時使用了 this.props.changeName,也就是父組件調用時傳遞過來的函數,向父組件傳遞了 nickName 的值 Parry。
父組件在接收到子組件的調用後,調用了父組件自身的函數 handleChangeName 修改了自身的 state 中的 name 的值為 Parry,也就是子組件傳遞過來的 Parry,所以同時,父組件的頁面上的值也同時由之前的 React 變更成了 Parry。

/**
* 章節: 03-04
* 子父組件通信,子組件的實現
* FilePath: /03-04/child-2-parent.js
* @Parry
*/

import React, {Component} from 'react'

export default class ChildComponent extends Component {
  constructor(props) {
    super(props)

    this.state = {
      name: 'React'
    }
  }

  handleChange() {
    const nickName = 'Parry';
    this.setState({name: nickName})
    //調用父組件傳遞過來的函數參數,傳遞值到父組件去。
    this
      .props
      .changeName(nickName)
  }

  render() {
    const {name} = this.state;
    return (
      <div>
        <p>Hello {name}!</p>
        <Button
          onPress={this
          .handleChange
          .bind(this)}
          title="修改一下 name 為 Parry"/>
      </div>
    )
  }
}

多級組件之間的通信

如果組件之間的父子層級非常多,需要進行組件之間的傳遞,這時候當然可以通過上面介紹的方法進行一級一級的傳遞,但是當這種組件間層級很深的時候,這樣的傳遞方法不是一個太好的方法。
解決的方法是首先要在設計 App 時,需要註意不能讓組件之間的層級關係太深,一是為了避免組件之間通信的冗長,還有一個原因是太深的嵌套邏輯,用戶體驗上也不會很好,可以想象一下用戶從最底層一層層操作返回到最頂層時的體驗。
第二就是可以使用如 context 對象或 global 等方式進行多級組件間的通信,但是這種方式不推薦。

無直接關係組件間通信

前面提到的都是有層級關係的組件間的通信方式,而如果組件間沒有層級的關係的話,可以通過如 AsyncStorage 或 JSON 文件等方式進行無直接關係組件間的通信。
當然,還可以使用 EventEmitter / EventTarget / EventDispatcher繼承或實現介面的方式、Signals 模式或 Publish / Subscribe 的廣播形式,都可以達到無直接關係組件間的通信。
這些組件間的通信方式使得組件之間的數據可以傳遞起來,後續的實戰章節會有詳細的代碼實現,這裡主要進行了理論部分的介紹。掌握這部分知識後才可以將 App 開發中的基本單位,也就是組件串聯起來。


截圖


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

-Advertisement-
Play Games
更多相關文章
  • 一、同步載入與非同步載入的形式 1. 同步載入 我們平時最常使用的就是這種同步載入形式:<script src="http://yourdomain.com/script.js"></script> 同步模式,又稱阻塞模式,會阻止瀏覽器的後續處理,停止了後續的解析,因此停止了後續的文件載入(如圖像)、 ...
  • 前言: 由於js 中this的指向受函數運行環境的影響,指向經常改變,使得開發變得困難和模糊,所以在封裝sdk,寫一些複雜函數的時候經常會用到this 指向綁定,以避免出現不必要的問題,call、apply、bind基本都能實現這一功能,現對這三種方法使用總結一下: 1、function.proto ...
  • keyup適用於文本框的數據輸入和同步,以及數據的獲取;keydown 與 keypress更適用於通過鍵盤控制頁面功能的實現(如回車事件) ...
  • function base64ToBlob(base64) { var arr = base64.split(','); var mime = arr[0].match(/:(.*?);/)[1] || 'image/png'; // 去掉url的頭,並轉化為byte var bytes = win... ...
  • 由於之前面試,被問到過此問題,所以今天特意整理了一下。由於自己技術水平有限,若存在錯誤,歡迎提出批評。 本博客整理了兩種方式從一個頁面層向另一個頁面層傳遞參數。 一. 通過cookie方式 1. 傳遞cookie頁面的html,此處命名為a.html 2.a.html的js代碼 3. 接受cooki ...
  • 從遠程clone一個倉庫 。。。知識淺薄 git clone都發現貌似用的不順 因為我有幾個git賬號 但是我也不知道就是git賬號是怎麼保存在終端上的 所以當我需要用一個新的github賬號來clone遠程倉庫的時候 我需要新換一個用戶名跟密碼 但是問題來了。。。 我不知道怎麼在 git clon ...
  • 不能直接把後臺返回的數組數據賦值到定義的空數組中,一定要concat連接,否則結果是看似是個數組,但是獲取到的該數組卻為空,導致第一次上拉載入更多的時候是拿到的之前的數組依然是空數組。 var config = require('../../config') var util = require(' ...
  • SVG在HTML頁面 SVG 是使用 XML 來描述二維圖形和繪圖程式的語言。 SVG 文件可通過以下標簽嵌入 HTML 文檔:、 或者 。SVG的代碼可以直接嵌入到HTML頁面中,或您可以直接鏈接到SVG文件。 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...