《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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...