日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

react- native 入门

發(fā)布時間:2024/4/15 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 react- native 入门 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

React Native 從入門到源碼

React Native 是最近非常火的一個話題,介紹如何利用 React Native 進行開發(fā)的文章和書籍多如牛毛,但面向入門水平并介紹它工作原理的文章卻寥寥無幾。

本文分為兩個部分:上半部分用通俗的語言解釋了相關(guān)的名詞,重點介紹 React Native 出現(xiàn)的背景和試圖解決的問題。適合新手對 React Native 形成初步了解。(事實證明,女票能看懂這段)

下半部分則通過源碼(0.27 版本)分析 React Native 的工作原理,適合深入學(xué)習(xí)理解 React Native 的運行機制。最后則是我個人對 React Native 的分析與前景判斷。

動態(tài)配置

由于 AppStore 審核周期的限制,如何動態(tài)的更改 app 成為了永恒的話題。無論采用何種方式,我們的流程總是可以歸結(jié)為以下三部曲:“從 Server 獲取配置 --> 解析 --> 執(zhí)行native代碼”。

很多時候,我們自覺或者不自覺的利用 JSON 文件實現(xiàn)動態(tài)配置的效果,它的核心流程是:

  • 通過 HTTP 請求獲取 JSON 格式的配置文件。
  • 配置文件中標(biāo)記了每一個元素的屬性,比如位置,顏色,圖片 URL 等。
  • 解析完 JSON 后,我們調(diào)用 Objective-C 的代碼,完成 UI 控件的渲染。
  • 通過這種方法,我們實現(xiàn)了在后臺配置 app 的展示樣式。從本質(zhì)上來說,移動端和服務(wù)端約定了一套協(xié)議,但是協(xié)議內(nèi)容嚴(yán)重依賴于應(yīng)用內(nèi)要展示的內(nèi)容,不利于拓展。也就是說,如果業(yè)務(wù)要求頻繁的增加或修改頁面,這套協(xié)議很難應(yīng)付。

    最重要的是,JSON 只是一種數(shù)據(jù)交換的格式,說白了,我們就是在解析文本數(shù)據(jù)。這就意味著它只適合提供一些配置信息,而不方便提供邏輯信息。舉個例子,我們從后臺可以配置顏色,位置等信息,但如果想要控制 app 內(nèi)的業(yè)務(wù)邏輯,就非常復(fù)雜了。

    記住,我們只是在解析字符串,它完全不具備運行和調(diào)試的能力。

    React

    不妨?xí)簳r拋棄移動端的煩惱,來看看前端的“新玩意”。

    背景

    作為前端小白,我以前對前端的理解是這樣的:

    • 用 HTML 創(chuàng)建 DOM,構(gòu)建整個網(wǎng)頁的布局、結(jié)構(gòu)
    • 用 CSS 控制 DOM 的樣式,比如字體、字號、顏色、居中等
    • 用 JavaScript 接受用戶事件,動態(tài)的操控 DOM

    在這三者的配合下,幾乎所有頁面上的功能都能實現(xiàn)。但也有比較不爽地方,比如我想動態(tài)修改一個按鈕的文字,我需要這樣寫:

    <button type="button" id="button" οnclick="onClick()">old button</button> ?

    然后在 JavaScript 中操作 DOM:

    <script> ?

    function onClick() { ?

    ? document.getElementById('button').innerHTML='new button';

    }

    </script> ?

    可以看到,在 HTML 和 JavaScript 代碼中,id 和 onclick 事件觸發(fā)的函數(shù)必須完全對應(yīng),否則就無法正確的響應(yīng)事件。如果想知道一個 HTML 標(biāo)簽會如何被響應(yīng),我們還得跑去 JavaScript 代碼中查找,這種原始的配置方式讓我覺得非常不爽。

    初識 React

    隨著 FaceBook 推出了 React 框架,這個問題得到了大幅度改善。我們可以把一組相關(guān)的 HTML 標(biāo)簽,也就是 app 內(nèi)的 UI 控件,封裝進一個組件(Component)中,我從阮一峰的 React 教程中摘錄了一段代碼:

    var MyComponent = React.createClass({ ?

    ? handleClick: function() {

    ? ? this.refs.myTextInput.focus();

    ? },

    ? render: function() {

    ? ? return (

    ? ? ? <div>

    ? ? ? ? <input type="text" ref="myTextInput" />

    ? ? ? ? <input type="button" value="Focus the text input" onClick={this.handleClick} />

    ? ? ? </div>

    ? ? );

    ? }

    });

    如果你想問:“為什么 JavaScript 代碼里面出現(xiàn)了 HTML 的語法”,那么恭喜你已經(jīng)初步體會到 React 的奧妙了。這種語法被稱為 JSX,它是一種 JavaScript 語法拓展。JSX 允許我們寫 HTML 標(biāo)簽或 React 標(biāo)簽,它們終將被轉(zhuǎn)換成原生的 JavaScript 并創(chuàng)建 DOM。

    在 React 框架中,除了可以用 JavaScript 寫 HTML 以外,我們甚至可以寫 CSS,這在后面的例子中可以看到。

    理解 React

    前端界總是喜歡創(chuàng)造新的概念,仿佛誰說的名詞更晦澀,誰的水平就越高。如果你和當(dāng)時的我一樣,聽到 React 這個概念一臉懵逼的話,只要記住以下定義即可:

    React 是一套可以用簡潔的語法高效繪制 DOM 的框架

    上文已經(jīng)解釋過了何謂“簡潔的語法”,因為我們可以暫時放下 HTML 和 CSS,只關(guān)心如何用 JavaScript 構(gòu)造頁面。

    所謂的“高效”,是因為 React 獨創(chuàng)了 Virtual DOM 機制。Virtual DOM 是一個存在于內(nèi)存中的 JavaScript 對象,它與 DOM 是一一對應(yīng)的關(guān)系,也就是說只要有 Virtual DOM,我們就能渲染出 DOM。

    當(dāng)界面發(fā)生變化時,得益于高效的 DOM Diff 算法,我們能夠知道 Virtual DOM 的變化,從而高效的改動 DOM,避免了重新繪制 DOM。

    當(dāng)然,React 并不是前端開發(fā)的全部。從之前的描述也能看出,它專注于 UI 部分,對應(yīng)到 MVC 結(jié)構(gòu)中就是 View 層。要想實現(xiàn)完整的 MVC 架構(gòu),還需要 Model 和 Controller 的結(jié)構(gòu)。在前端開發(fā)時,我們可以采用 Flux 和 Redux 架構(gòu),它們并非框架(Library),而是和 MVC 一樣都是一種架構(gòu)設(shè)計(Architecture)。

    如果不從事前端開發(fā),就不用深入的掌握 Flux 和 Redux 架構(gòu),但理解這一套體系結(jié)構(gòu)對于后面理解 React Native 非常重要。

    React Native

    分別介紹完了移動端和前端的背景知識后,本文的主角——React Native 終于要登場了。

    融合

    前面我們介紹了移動端通過 JSON 文件傳遞信息的不足之處:只能傳遞配置信息,無法表達邏輯。從本質(zhì)上講,這是因為 JSON 畢竟只是純文本,它缺乏像編程語言那樣的運行能力。

    而 React 在前端取得突破性成功以后,JavaScript 布道者們開始試圖一統(tǒng)三端。他們利用了移動平臺能夠運行 JavaScript 代碼的能力,并且發(fā)揮了 JavaScript 不僅僅可以傳遞配置信息,還可以表達邏輯信息的優(yōu)點。

    當(dāng)痛點遇上特點,兩者一拍即合,于是乎:

    一個基于 JavaScript,具備動態(tài)配置能力,面向前端開發(fā)者的移動端開發(fā)框架,React Native,誕生了!

    看到了么,這是一個面向前端開發(fā)者的框架。它的宗旨是讓前端開發(fā)者像用 React 寫網(wǎng)頁那樣,用 React Native 寫移動端應(yīng)用。這就是為什么 React Native 自稱:

    Learn once,Write anywhere!

    而非很多跨平臺語言,項目所說的:

    Write once, Run anywhere!

    React Native 希望前端開發(fā)者學(xué)習(xí)完 React 后,能夠用同樣的語法、工具等,分別開發(fā)安卓和 iOS 平臺的應(yīng)用并且不用一行原生代碼。

    如果用一個詞概括 React Native,那就是:Native 版本的 React。

    原理概述

    React Native 不是黑科技,我們寫的代碼總是以一種非常合理,可以解釋的方式的運行著,只是絕大多數(shù)人沒有理解而已。接下來我以 iOS 平臺為例,簡單的解釋一下 React Native 的原理。

    首先要明白的一點是,即使使用了 React Native,我們依然需要 UIKit 等框架,調(diào)用的是 Objective-C 代碼。總之,JavaScript 只是輔助,它只是提供了配置信息和邏輯的處理結(jié)果。React Native 與 Hybrid 完全沒有關(guān)系,它只不過是以 JavaScript 的形式告訴 Objective-C 該執(zhí)行什么代碼。

    其次,React Native 能夠運行起來,全靠 Objective-C 和 JavaScript 的交互。對于沒有接觸過 JavaScript 的人來說,非常有必要理解 JavaScript 代碼如何被執(zhí)行。

    我們知道 C 系列的語言,經(jīng)過編譯,鏈接等操作后,會得到一個二進制格式的可執(zhí)行文,所謂的運行程序,其實是運行這個二進制程序。

    而 JavaScript 是一種腳本語言,它不會經(jīng)過編譯、鏈接等操作,而是在運行時才動態(tài)的進行詞法、語法分析,生成抽象語法樹(AST)和字節(jié)碼,然后由解釋器負責(zé)執(zhí)行或者使用 JIT 將字節(jié)碼轉(zhuǎn)化為機器碼再執(zhí)行。整個流程由 JavaScript 引擎負責(zé)完成。

    蘋果提供了一個叫做 JavaScript Core 的框架,這是一個 JavaScript 引擎。通過下面這段代碼可以簡單的感受一下 Objective-C 如何調(diào)用 JavaScript 代碼:

    JSContext *context = [[JSContext alloc] init]; ?

    JSValue *jsVal = [context evaluateScript:@"21+7"]; ?

    int iVal = [jsVal toInt32]; ?

    這里的 JSContext 指的是 JavaScript 代碼的運行環(huán)境,通過 evaluateScript 即可執(zhí)行 JavaScript 代碼并獲取返回結(jié)果。

    JavaScript 是一種單線程的語言,它不具備自運行的能力,因此總是被動調(diào)用。很多介紹 React Native 的文章都會提到 “JavaScript 線程” 的概念,實際上,它表示的是 Objective-C 創(chuàng)建了一個單獨的線程,這個線程只用于執(zhí)行 JavaScript 代碼,而且 JavaScript 代碼只會在這個線程中執(zhí)行。

    Objective-C 與 JavaScript 交互

    提到 Objective-C 與 JavaScript 的交互,不得不推薦 bang神的這篇文章:React Native通信機制詳解 。雖然其中不少細節(jié)都已經(jīng)過時,但是整體的思路值得學(xué)習(xí)。

    本節(jié)主要分析 Objective-C 與 JavaScript 交互時的整理邏輯與流程,下一節(jié)將通過源碼來分析具體原理。

    JavaScript 調(diào)用 Objective-C

    由于 JavaScript Core 是一個面向 Objective-C 的框架,在 Objective-C 這一端,我們對 JavaScript 上下文知根知底,可以很容易的獲取到對象,方法等各種信息,當(dāng)然也包括調(diào)用 JavaScript 函數(shù)。

    真正復(fù)雜的問題在于,JavaScript 不知道 Objective-C 有哪些方法可以調(diào)用。

    React Native 解決這個問題的方案是在 Objective-C 和 JavaScript 兩端都保存了一份配置表,里面標(biāo)記了所有 Objective-C 暴露給 JavaScript 的模塊和方法。這樣,無論是哪一方調(diào)用另一方的方法,實際上傳遞的數(shù)據(jù)只有 ModuleId、MethodId 和 Arguments 這三個元素,它們分別表示類、方法和方法參數(shù),當(dāng) Objective-C 接收到這三個值后,就可以通過 runtime 唯一確定要調(diào)用的是哪個函數(shù),然后調(diào)用這個函數(shù)。

    再次重申,上述解決方案只是一個抽象概念,可能與實際的解決方案有微小差異,比如實際上 Objective-C 這一端,并沒有直接保存這個模塊配置表。具體實現(xiàn)將在下一節(jié)中隨著源碼一起分析。

    閉包與回調(diào)

    既然說到函數(shù)互調(diào),那么就不得不提到回調(diào)了。對于 Objective-C 來說,執(zhí)行完 JavaScript 代碼再執(zhí)行 Objective-C 回調(diào)毫無難度,難點依然在于 JavaScript 代碼調(diào)用 Objective-C 之后,如何在 Objective-C 的代碼中,回調(diào)執(zhí)行 JavaScript 代碼。

    目前 React Native 的做法是:在 JavaScript 調(diào)用 Objective-C 代碼時,注冊要回調(diào)的 Block,并且把 BlockId 作為參數(shù)發(fā)送給 Objective-C,Objective-C 收到參數(shù)時會創(chuàng)建 Block,調(diào)用完 Objective-C 函數(shù)后就會執(zhí)行這個剛剛創(chuàng)建的 Block。

    Objective-C 會向 Block 中傳入?yún)?shù)和 BlockId,然后在 Block 內(nèi)部調(diào)用 JavaScript 的方法,隨后 JavaScript 查找到當(dāng)時注冊的 Block 并執(zhí)行。

    圖解

    好吧,如果你是新手,并且堅持讀到了這里,估計已經(jīng)懵逼了。不要擔(dān)心,與 JavaScript 的交互確實不是一下子能夠完全理清楚的,你可以先參考這個示意圖:

    注:

  • 本圖由 bang 的文章中的圖片修改而來
  • 本圖只是一個簡單的示意圖,不建議當(dāng)做時序圖使用,請參考下一節(jié)源碼分析。
  • Objective-C 和 JavaScript 的交互總是由前者發(fā)起,本圖為了簡化,省略了這一步驟。
  • React Native 源碼分析

    要想深入理解 React Native 的工作原理,有兩個部分有必要閱讀一下,分別是初始化階段和方法調(diào)用階段。

    為了提煉出代碼的核心含義,我會在不改變代碼意圖的基礎(chǔ)上對它做一些刪改,以便閱讀。

    寫這篇文章是,React Native 還處于 0.27 版本,由于在 1.0 之前的變動幅度相對較大,因此下面的源碼分析很可能隨著 React Native 的演變而過時。但不管何時,把下面的源碼讀一遍都有助于你加深對 React Native 原理的理解。

    初始化 React Native

    每個項目都有一個入口,然后進行初始化操作,React Native 也不例外。一個不含 Objective-C 代碼的項目留給我們的唯一線索就是位于 AppDelegate 文件中的代碼:

    RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation ?

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? moduleName:@"PropertyFinder"

    ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? initialProperties:nil

    ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? launchOptions:launchOptions];

    用戶能看到的一切內(nèi)容都來源于這個 RootView,所有的初始化工作也都在這個方法內(nèi)完成。

    在這個方法內(nèi)部,在創(chuàng)建 RootView 之前,React Native 實際上先創(chuàng)建了一個 Bridge 對象。它是 Objective-C 與 JavaScript 交互的橋梁,后續(xù)的方法交互完全依賴于它,而整個初始化過程的最終目的其實也就是創(chuàng)建這個橋梁對象。

    初始化方法的核心是 setUp 方法,而 setUp 方法的主要任務(wù)則是創(chuàng)建 BatchedBridge。

    BatchedBridge 的作用是批量讀取 JavaScript 對 Objective-C 的方法調(diào)用,同時它內(nèi)部持有一個 JavaScriptExecutor,顧名思義,這個對象用來執(zhí)行 JavaScript 代碼。

    創(chuàng)建 BatchedBridge 的關(guān)鍵是 start 方法,它可以分為五個步驟:

  • 讀取 JavaScript 源碼
  • 初始化模塊信息
  • 初始化 JavaScript 代碼的執(zhí)行器,即 RCTJSCExecutor 對象
  • 生成模塊列表并寫入 JavaScript 端
  • 執(zhí)行 JavaScript 源碼
  • 我們逐個分析每一步完成的操作:

    讀取 JavaScript 源碼

    這一部分的具體代碼實現(xiàn)沒有太大的討論意義。我們只要明白,JavaScript 的代碼是在 Objective-C 提供的環(huán)境下運行的,所以第一步就是把 JavaScript 加載進內(nèi)存中,對于一個空的項目來說,所有的 JavaScript 代碼大約占用 1.5 Mb 的內(nèi)存空間。

    需要說明的是,在這一步中,JSX 代碼已經(jīng)被轉(zhuǎn)化成原生的 JavaScript 代碼。

    初始化模塊信息

    這一步在方法 initModulesWithDispatchGroup: 中實現(xiàn),主要任務(wù)是找到所有需要暴露給 JavaScript 的類。每一個需要暴露給 JavaScript 的類(也成為 Module,以下不作區(qū)分)都會標(biāo)記一個宏:RCT_EXPORT_MODULE,這個宏的具體實現(xiàn)并不復(fù)雜:

    #define RCT_EXPORT_MODULE(js_name) \

    RCT_EXTERN void RCTRegisterModule(Class); \ ?

    + (NSString *)moduleName { return @#js_name; } \

    + (void)load { RCTRegisterModule(self); }

    這樣,這個類在 load 方法中就會調(diào)用 RCTRegisterModule 方法注冊自己:

    void RCTRegisterModule(Class moduleClass) ?

    {

    ? static dispatch_once_t onceToken;

    ? dispatch_once(&onceToken, ^{

    ? ? RCTModuleClasses = [NSMutableArray new];

    ? });

    ?

    ? [RCTModuleClasses addObject:moduleClass];

    }

    因此,React Native 可以通過 RCTModuleClasses 拿到所有暴露給 JavaScript 的類。下一步操作是遍歷這個數(shù)組,然后生成 RCTModuleData 對象:

    for (Class moduleClass in RCTGetModuleClasses()) { ?

    ? ? RCTModuleData *moduleData = [[RCTModuleData alloc]initWithModuleClass:moduleClass? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? bridge:self];

    ? ? [moduleClassesByID addObject:moduleClass];

    ? ? [moduleDataByID addObject:moduleData];

    }

    可以想見,RCTModuleData 對象是模塊配置表的主要組成部分。如果把模塊配置表想象成一個數(shù)組,那么每一個元素就是一個 RCTModuleData 對象。

    這個對象保存了 Module 的名字,常量等基本信息,最重要的屬性是一個數(shù)組,保存了所有需要暴露給 JavaScript 的方法。

    暴露給 JavaScript 的方法需要用 RCT_EXPORT_METHOD 這個宏來標(biāo)記,它的實現(xiàn)原理比較復(fù)雜,有興趣的讀者可以自行閱讀。簡單來說,它為函數(shù)名加上了 __rct_export__ 前綴,再通過 runtime 獲取類的函數(shù)列表,找出其中帶有指定前綴的方法并放入數(shù)組中:

    - (NSArray<id<RCTBridgeMethod>> *)methods{

    ? ? unsigned int methodCount;

    ? ? Method *methods = class_copyMethodList(object_getClass(_moduleClass), &methodCount); // 獲取方法列表

    ? ? for (unsigned int i = 0; i < methodCount; i++) {

    ? ? ? ? RCTModuleMethod *moduleMethod = /* 創(chuàng)建 method */

    ? ? ? ? [_methods addObject:moduleMethod];

    ? ? ? }

    ? ? }

    ? ? return _methods;

    }

    因此 Objective-C 管理模塊配置表的邏輯是:Bridge 持有一個數(shù)組,數(shù)組中保存了所有的模塊的 RCTModuleData 對象。只要給定 ModuleId 和 MethodId 就可以唯一確定要調(diào)用的方法。

    初始化 JavaScript 代碼的執(zhí)行器,即 RCTJSCExecutor 對象

    通過查看源碼可以看到,初始化 JavaScript 執(zhí)行器的時候,addSynchronousHookWithName 這個方法被調(diào)用了多次,它其實向 JavaScript 上下文中添加了一些 Block 作為全局變量:

    - (void)addSynchronousHookWithName:(NSString *)name usingBlock:(id)block {

    ? ? self.context.context[name] = block;

    }

    有些同學(xué)讀源碼時可能會走進一個誤區(qū),如果在 Block 中打一個斷點就會發(fā)現(xiàn),Block 其實是被執(zhí)行了,但卻找不到任何能夠執(zhí)行 Block 的代碼。

    這其實是因為這個 Block 并非由 Objective-C 主動調(diào)用,而是在第五步執(zhí)行 JavaScript 代碼時,由 JavaScript 在上下文中獲取到 Block 對象并調(diào)用,有興趣的讀者可以自行添加斷點并驗證。

    這里我們需要重點注意的是名為 nativeRequireModuleConfig 的 Block,它在 JavaScript 注冊新的模塊時調(diào)用:

    get: () => { ?

    ? ? let module = RemoteModules[moduleName];

    ? ? const json = global.nativeRequireModuleConfig(moduleName); // 調(diào)用 OC 的 Block

    ? ? const config = JSON.parse(json); // 解析 json

    ? ? module = BatchedBridge.processModuleConfig(config, module.moduleID); // 注冊 config

    ? ? return module;

    },

    這就是模塊配置表能夠加載到 JavaScript 中的原理。

    另一個值得關(guān)注的 Block 叫做 nativeFlushQueueImmediate。實際上,JavaScript 除了把調(diào)用信息放到 MessageQueue 中等待 Objective-C 來取以外,也可以主動調(diào)用 Objective-C 的方法:

    if (global.nativeFlushQueueImmediate && ?

    ? ? now - this._lastFlush >= MIN_TIME_BETWEEN_FLUSHES_MS) {

    ? ? global.nativeFlushQueueImmediate(this._queue); // 調(diào)用 OC 的代碼

    }

    目前,React Native 的邏輯是,如果消息隊列中有等待 Objective-C 處理的邏輯,而且 Objective-C 超過 5ms 都沒有來取走,那么 JavaScript 就會主動調(diào)用 Objective-C 的方法:

    [self addSynchronousHookWithName:@"nativeFlushQueueImmediate" usingBlock:^(NSArray<NSArray *> *calls){

    ? ? [self->_bridge handleBuffer:calls batchEnded:NO];

    }];

    這個 handleBuffer 方法是 JavaScript 調(diào)用 Objective-C 方法的關(guān)鍵,在下一節(jié)——方法調(diào)用中,我會詳細分析它的實現(xiàn)原理。

    一般情況下,Objective-C 會定時、主動的調(diào)用 handleBuffer 方法,這有點類似于輪詢機制:

    // 每個一段時間發(fā)生一次:

    Objective-C:嘿,JavaScript,有沒有要調(diào)用我的方法呀? ?

    JavaScript:有的,你從 MessageQueue 里面取出來。 ?

    然而由于卡頓或某些特殊原因,Objective-C 并不能總是保證能夠準(zhǔn)時的清空 MessageQueue,這就是為什么 JavaScript 也會在一定時間后主動的調(diào)用 Objective-C 的方法。查看上面 JavaScript 的代碼可以發(fā)現(xiàn),這個等待時間是 5ms。

    請牢牢記住這個 5ms,它告訴我們 JavaScript 與 Objective-C 的交互是存在一定開銷的,不然就不會等待而是每次都立刻發(fā)起請求。其次,這個時間開銷大約是毫秒級的,不會比 5ms 小太多,否則等待這么久就意義不大了。

    生成模塊配置表并寫入 JavaScript 端

    復(fù)習(xí)一下 nativeRequireModuleConfig 這個 Block,它可以接受 ModuleName 并且生成詳細的模塊信息,但在前文中我們沒有提到 JavaScript 是如何知道 Objective-C 要暴露哪些類的(目前只是 Objective-C 自己知道)。

    這一步的操作就是為了讓 JavaScript 獲取所有模塊的名字:

    - (NSString *)moduleConfig{

    ? ? NSMutableArray<NSArray *> *config = [NSMutableArray new];

    ? ? for (RCTModuleData *moduleData in _moduleDataByID) {

    ? ? ? [config addObject:@[moduleData.name]];

    ? ? }

    }

    查看源碼可以發(fā)現(xiàn),Objective-C 把 config 字符串設(shè)置成 JavaScript 的一個全局變量,名字叫做:__fbBatchedBridgeConfig。

    執(zhí)行 JavaScript 源碼

    這一步也沒什么技術(shù)難度可以,代碼已經(jīng)加載進了內(nèi)存,該做的配置也已經(jīng)完成,只要把 JavaScript 代碼運行一遍即可。

    運行代碼時,第三步中所說的那些 Block 就會被執(zhí)行,從而向 JavaScript 端寫入配置信息。

    至此,JavaScript 和 Objective-C 都具備了向?qū)Ψ浇换サ哪芰?#xff0c;準(zhǔn)備工作也就全部完成了。

    畫了一個簡陋的時序圖以供參考:

    方法調(diào)用

    如前文所述,在 React Native 中,Objective-C 和 JavaScript 的交互都是通過傳遞 ModuleId、MethodId 和 Arguments 進行的。以下是分情況討論:

    調(diào)用 JavaScript 代碼

    也許你在其他文章中曾經(jīng)多次聽說 JavaScript 代碼總是在一個單獨的線程上面調(diào)用,它的實際含義是 Objective-C 會在單獨的線程上運行 JavaScript 代碼:

    - (void)executeBlockOnJavaScriptQueue:(dispatch_block_t)block

    {

    ? if ([NSThread currentThread] != _javaScriptThread) {

    ? ? [self performSelector:@selector(executeBlockOnJavaScriptQueue:)

    ?? ? ? ? ? ? ? ? onThread:_javaScriptThread withObject:block waitUntilDone:NO];

    ? } else {

    ? ? block();

    ? }

    }

    調(diào)用 JavaScript 代碼的核心代碼如下:

    - (void)_executeJSCall:(NSString *)method

    ?? ? ? ? ? ? arguments:(NSArray *)arguments

    ? ? ? ? ? ? ? callback:(RCTJavaScriptCallback)onComplete{

    ? ? [self executeBlockOnJavaScriptQueue:^{

    ? ? ? ? // 獲取 contextJSRef、methodJSRef、moduleJSRef

    ? ? ? ? resultJSRef = JSObjectCallAsFunction(contextJSRef, (JSObjectRef)methodJSRef, (JSObjectRef)moduleJSRef, arguments.count, jsArgs, &errorJSRef);

    ? ? ? ? objcValue = /*resultJSRef 轉(zhuǎn)換成 Objective-C 類型*/

    ? ? ? ? onComplete(objcValue, nil);

    ? ? }];

    }

    需要注意的是,這個函數(shù)名是我們要調(diào)用 JavaScript 的中轉(zhuǎn)函數(shù)名,比如 callFunctionReturnFlushedQueue。也就是說它的作用其實是處理參數(shù),而非真正要調(diào)用的 JavaScript 函數(shù)。

    這個中轉(zhuǎn)函數(shù)接收到的參數(shù)包含了 ModuleId、MethodId 和 Arguments,然后由中轉(zhuǎn)函數(shù)查找自己的模塊配置表,找到真正要調(diào)用的 JavaScript 函數(shù)。

    在實際使用的時候,我們可以這樣發(fā)起對 JavaScript 的調(diào)用:

    [_bridge.eventDispatcher sendAppEventWithName:@"greeted"

    ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? body:@{ @"name": @"nmae"}];

    這里的 Name 和 Body 參數(shù)分別表示要調(diào)用的 JavaScript 的函數(shù)名和參數(shù)。

    JavaScript 調(diào)用 Objective-C

    在調(diào)用 Objective-C 代碼時,如前文所述,JavaScript 會解析出方法的 ModuleId、MethodId 和 Arguments 并放入到 MessageQueue 中,等待 Objective-C 主動拿走,或者超時后主動發(fā)送給 Objective-C。

    Objective-C 負責(zé)處理調(diào)用的方法是 handleBuffer,它的參數(shù)是一個含有四個元素的數(shù)組,每個元素也都是一個數(shù)組,分別存放了 ModuleId、MethodId、Params,第四個元素目測用處不大。

    函數(shù)內(nèi)部在每一次方調(diào)用中調(diào)用 _handleRequestNumber:moduleID:methodID:params 方法。,通過查找模塊配置表找出要調(diào)用的方法,并通過 runtime 動態(tài)的調(diào)用:

    [method invokeWithBridge:self module:moduleData.instance arguments:params];

    在這個方法中,有一個很關(guān)鍵的方法:processMethodSignature,它會根據(jù) JavaScript 的 CallbackId 創(chuàng)建一個 Block,并且在調(diào)用完函數(shù)后執(zhí)行這個 Block。

    實戰(zhàn)應(yīng)用

    俗話說:“思而不學(xué)則神棍”,下面舉一個例子來演示 Objective-C 是如何與 JavaScript 進行交互的。首先新建一個模塊:

    // .h 文件

    #import <Foundation/Foundation.h>

    #import "RCTBridgeModule.h"

    ?

    @interface Person : NSObject<RCTBridgeModule, RCTBridgeMethod>

    ?

    @end

    Person 這個類是一個新的模塊,它有兩個方法暴露給 JavaScript:

    #import "Person.h"

    #import "RCTEventDispatcher.h"

    #import "RCTConvert.h"

    ?

    @implementation Person

    @synthesize bridge = _bridge;

    ?

    RCT_EXPORT_MODULE();

    ?

    RCT_EXPORT_METHOD(greet:(NSString *)name) ?

    {

    ? NSLog(@"Hi, %@!", name);

    ? [_bridge.eventDispatcher sendAppEventWithName:@"greeted"

    ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? body:@{ @"name": @"nmae"}];

    }

    ?

    RCT_EXPORT_METHOD(greetss:(NSString *)name name2:(NSString *)name2 callback:(RCTResponseSenderBlock)callback) ?

    {

    ? NSLog(@"Hi, %@! %@!!!", name, name2);

    ? callback(@[@[@12,@23,@34]]);

    }

    ?

    @end

    在 JavaScript 中,可以這樣調(diào)用:

    Person.greet('Tadeu'); ?

    Person.greetss('Haha', 'Heihei', (events) => { ?

    ? for (var i = 0; i < events.length; i++) {

    ? ? console.log(events[i]);

    ? }

    });

    有興趣的同學(xué)可以復(fù)制以上代碼并自行調(diào)試。

    React Native 優(yōu)缺點分析

    經(jīng)過一長篇的討論,其實 React Native 的優(yōu)缺點已經(jīng)不難分析了,這里簡單總結(jié)一下:

    優(yōu)點

  • 復(fù)用了 React 的思想,有利于前端開發(fā)者涉足移動端。
  • 能夠利用 JavaScript 動態(tài)更新的特性,快速迭代。
  • 相比于原生平臺,開發(fā)速度更快,相比于 Hybrid 框架,性能更好。
  • 缺點

  • 做不到 Write once, Run everywhere,也就是說開發(fā)者依然需要為 iOS 和 Android 平臺提供兩套不同的代碼,比如參考官方文檔可以發(fā)現(xiàn)不少組件和API都區(qū)分了 Android 和 iOS 版本。即使是共用組件,也會有平臺獨享的函數(shù)。
  • 不能做到完全屏蔽 iOS 端或 Android 的細節(jié),前端開發(fā)者必須對原生平臺有所了解。加重了學(xué)習(xí)成本。對于移動端開發(fā)者來說,完全不具備用 React Native 開發(fā)的能力。
  • 由于 Objective-C 與 JavaScript 之間切換存在固定的時間開銷,所以性能必定不及原生。比如目前的官方版本無法做到 UItableview(ListView) 的視圖重用,因為滑動過程中,視圖重用需要在異步線程中執(zhí)行,速度太慢。這也就導(dǎo)致隨著 Cell 數(shù)量的增加,占用的內(nèi)存也線性增加。
  • 綜上,我對 React Native 的定位是:

    利用腳本語言進行原生平臺開發(fā)的一次成功嘗試,降低了前端開發(fā)者入門移動端的門檻,一定業(yè)務(wù)場景下具有獨特的優(yōu)勢,幾乎不可能取代原生平臺開發(fā)。

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/ChrisZhou666/p/5888691.html

    超強干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達旦的技術(shù)人生

    總結(jié)

    以上是生活随笔為你收集整理的react- native 入门的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    黄色大片免费播放 | 久久精品久久国产 | 国内免费的中文字幕 | 日本黄色免费网站 | 久久国语 | 久久你懂的| 中文字幕一区二区三区在线播放 | 在线观看视频你懂得 | 日韩大片免费在线观看 | 欧美一区二区三区在线看 | 日韩精品一区二区三区第95 | 日韩欧美在线不卡 | 亚洲五月 | 99精品国产免费久久 | 天天干天天上 | 免费成人短视频 | 99视频在线免费播放 | www.色午夜,com | 国产精品女主播一区二区三区 | 久久久久免费精品视频 | 亚洲黄色一级电影 | 最新av网址大全 | 男女拍拍免费视频 | 在线直播av | 日色在线视频 | 亚洲国产精品成人综合 | 深爱婷婷网 | 亚洲精品黄色在线观看 | av一级在线| 久久精品一区二区三区四区 | 97人人网 | 国产精品久久久久久欧美 | 麻豆果冻剧传媒在线播放 | 欧美日韩一二三四区 | 日韩在线网址 | 99精品一区二区 | 久久a v视频 | 在线观看91视频 | 欧美日本不卡高清 | 欧美日韩一级视频 | 国产精品一码二码三码在线 | 麻豆久久久久 | 欧美九九九 | 亚洲jizzjizz日本少妇 | 在线视频第一页 | 色综合www | 色天天综合久久久久综合片 | 亚洲国产99 | 日日草天天草 | 激情综合婷婷 | 97电影手机版 | 天天干天天射天天插 | 天天操婷婷| 在线观看播放av | 日韩国产精品久久 | 欧美在线观看视频一区二区 | 日日夜夜天天综合 | 免费男女羞羞的视频网站中文字幕 | 97超碰站 | 中文字幕精品一区二区三区电影 | 国产视频日韩视频欧美视频 | 亚洲精品理论 | 成人在线一区二区 | 午夜.dj高清免费观看视频 | 免费三级影片 | 久久国产精品99久久人人澡 | 三级在线视频播放 | 天天干天天弄 | 国产黄色片免费观看 | 黄色一级免费网站 | 亚洲午夜精品电影 | 三级av片 | 国产一区私人高清影院 | 国产九九九九九 | 911免费视频| 三级免费黄色 | 一性一交视频 | 欧美激情视频一二区 | 天天鲁天天干天天射 | 欧美久久影院 | 毛片基地黄久久久久久天堂 | 欧美精品亚洲精品日韩精品 | 日韩com| 国产精品亚洲人在线观看 | 亚洲欧美在线综合 | 狠狠黄| 一级黄色电影网站 | 五月开心六月婷婷 | 久久久网址 | 97视频在线播放 | 日日干视频 | 又黄又爽又刺激视频 | 欧美日韩一区二区在线观看 | 日韩视频免费 | 免费情缘| 麻豆国产精品永久免费视频 | 一区二区激情视频 | 国产又粗又猛又色又黄视频 | 国产亚州精品视频 | 久久久999 | 不卡视频一区二区三区 | 日韩中文字幕免费视频 | 久久综合九九 | 亚洲精品国产精品国自产在线 | 国产一级二级三级视频 | 在线观看免费高清视频大全追剧 | 国产成人精品一区二三区 | 久久免费精品 | 久久99网站 | 亚洲v欧美v国产v在线观看 | 五月婷婷中文网 | 97精品国产97久久久久久粉红 | 日韩欧美一区二区三区视频 | 免费av福利 | 激情五月六月婷婷 | 九九综合久久 | 国产群p视频 | 69精品久久久 | 色鬼综合网 | 久久人人爽人人爽人人片av免费 | 久爱精品在线 | 一区二区三区视频 | 99久e精品热线免费 99国产精品久久久久久久久久 | 欧美日韩成人 | 91精品综合在线观看 | 国产91全国探花系列在线播放 | 国产小视频在线免费观看视频 | 18网站在线观看 | 狠狠色伊人亚洲综合网站野外 | av在线免费网 | 奇米网8888 | 亚洲精选在线观看 | 中日韩欧美精彩视频 | 欧美综合色在线图区 | 国产日韩在线看 | 欧美999| 91精品伦理 | 黄影院| 国产在线观看你懂得 | 狠狠干网站| 亚洲高清视频在线 | 中文字幕av在线电影 | 高潮毛片无遮挡高清免费 | 成人免费 在线播放 | 在线欧美国产 | 99精品视频免费在线观看 | 国产激情电影综合在线看 | 免费黄在线观看 | 亚洲美女视频网 | av不卡在线看 | 国产一区二区网址 | 色婷婷免费 | 99精品在线免费在线观看 | 日韩欧美一区二区在线观看 | 国产亚洲一区 | 四虎在线免费视频 | 免费久久网| 亚洲精品视频中文字幕 | 日韩黄色网络 | 91黄色影视 | 伊人黄色网 | 免费高清在线观看电视网站 | 久久久美女 | 国产在线播放观看 | 国产一区av在线 | 精品国产乱码一区二 | 国产精品一码二码三码在线 | 久久久久久久久影院 | 国产亚洲欧美日韩高清 | 婷婷婷国产在线视频 | 五月激情丁香图片 | 日本二区三区在线 | 一区二区三区高清 | 国产精久久久久久妇女av | 亚洲国产高清在线观看视频 | 天天综合导航 | 在线a视频免费观看 | 欧美成人一区二区 | 精品视频在线看 | 欧美久久久久久久久久 | 成人影片免费 | 精品国产一区二区三区蜜臀 | 91精品国自产在线观看欧美 | 国产午夜精品一区二区三区四区 | avwww在线| 一级黄色av | 国产精品久久久久久久久蜜臀 | 亚洲精品mv在线观看 | 婷婷六月久久 | 18av在线视频 | 91成人看片| 国产欧美中文字幕 | 日日干美女 | 国产成人91 | 黄色福利网站 | 狠狠躁18三区二区一区ai明星 | 精品一区二区在线播放 | 麻豆 free xxxx movies hd| 国产在线精品区 | 九九热精品在线 | 国产色拍拍拍拍在线精品 | 免费a v网站| 五月开心激情 | www.888av| 精品国产片| 国产亚洲精品久久久久久电影 | 香蕉视频在线看 | 中文字幕在线久一本久 | 一区免费观看 | 国产精品久久久久久久久久免费看 | 九月婷婷综合网 | 国产色资源| 久久久久久久影视 | 97超碰中文 | 极品久久久 | 永久av免费在线观看 | 国产精品第三页 | 久久国产精品99久久人人澡 | 日本护士撒尿xxxx18 | 午夜视频不卡 | 亚洲理论在线观看电影 | 日本三级人妇 | 日本精品久久久一区二区三区 | 亚洲春色成人 | 色天天综合久久久久综合片 | 六月色丁 | 日韩免费电影网 | 麻豆视频在线免费观看 | 色综合久久久久综合体桃花网 | 国产在线免费观看 | 免费看片在线观看 | 91亚洲精品在线 | 精品在线视频一区二区三区 | 久久久久久久精 | 免费在线观看黄 | 麻豆视频91| 一区二区三区精品久久久 | 中文字幕在线观看完整版电影 | 亚洲黑丝少妇 | 97影视 | 午夜精品婷婷 | 一级欧美一级日韩 | 97精品视频在线播放 | 中文字幕成人一区 | 精品国内自产拍在线观看视频 | 中文字幕高清视频 | 国内一区二区视频 | 久久刺激视频 | 在线观看成人毛片 | 国产精品午夜久久 | 亚洲欧美日韩国产精品一区午夜 | 国产精品福利午夜在线观看 | 久久精品女人毛片国产 | 99 久久久久| 永久黄网站色视频免费观看w | a久久久久 | 中文字幕在线观看三区 | 亚洲免费视频观看 | 五月婷婷中文 | 字幕网在线观看 | 日韩欧美精品一区二区三区经典 | 在线观看网站黄 | 国产麻豆果冻传媒在线观看 | 五月婷婷丁香在线观看 | 中文字幕 国产精品 | 激情综合五月天 | 国产69精品久久久久99 | 日韩丝袜| 99精品色| 国产精品永久免费在线 | 亚洲国产黄色 | 午夜视频黄 | 国产精品一二三 | 婷婷丁香久久五月婷婷 | 中文字幕永久在线 | 九九九九九国产 | 午夜91在线 | 久久精品久久久久电影 | 午夜电影av | 中文十次啦 | 久久精品一区二区三区国产主播 | 丁香激情五月 | 天天干天天做天天爱 | 成人av直播 | www.成人久久 | 精品久久久久久国产 | 黄色免费在线看 | 992tv又爽又黄的免费视频 | adn—256中文在线观看 | 亚洲精品乱码久久久久久蜜桃欧美 | 国产精品久久久久久久久久ktv | 免费视频91蜜桃 | 精品一区二区在线观看 | 一区二区三区不卡在线 | 久久精品人 | 国产91对白在线播 | 中文字幕一区二区三区乱码在线 | 国产女人免费看a级丨片 | 在线观看中文字幕网站 | a级片网站 | 国产精品免费视频一区二区 | 国产一级二级在线观看 | 毛片美女网站 | 国产精品一区二区三区99 | 色综合狠狠干 | bbw av| 亚洲第一区精品 | 亚洲成人av一区二区 | 91精品国产乱码在线观看 | 五月天丁香综合 | 国产护士hd高朝护士1 | 中文字幕精品视频 | 天天射夜夜爽 | 久久久久国产精品厨房 | 久久精品99北条麻妃 | 狠色在线| 日韩超碰| 午夜美女福利直播 | 久久久免费高清视频 | 国产美女精品人人做人人爽 | 国产在线观看网站 | 日韩免费在线视频观看 | 国产美女视频黄a视频免费 久久综合九色欧美综合狠狠 | 亚洲一区二区精品在线 | 免费黄色av. | 亚洲一区二区视频在线播放 | 四虎永久免费网站 | 国产99一区 | 国产精品男女啪啪 | 五月婷久 | 欧美一区二区免费在线观看 | 在线观看黄色小视频 | 亚洲精品成人av在线 | 偷拍视频一区 | 干av在线 | 成人黄色中文字幕 | 色香网 | 91av蜜桃| 一区二区三区三区在线 | 欧美精品久久久久久久久久白贞 | 国内精品久久久久久久久久清纯 | 天操夜夜操 | 国产精品欧美久久久久三级 | 国产xvideos免费视频播放 | 国内精品久久久久国产 | 黄色成人毛片 | 国产精品欧美久久久久久 | 在线看av的网址 | 天天色天天爱天天射综合 | 国产精选在线 | 成 人 黄 色 片 在线播放 | 中文字幕激情 | 91成版人在线观看入口 | 色狠狠一区二区 | 久久免费在线观看 | 麻豆视频国产 | 91视频电影 | 激情五月在线视频 | 天天操夜夜叫 | 免费看片亚洲 | 一二三区视频在线 | 99热在线国产 | 亚洲成年人免费网站 | 国产黄在线观看 | 久久人人97超碰国产公开结果 | 狠狠操导航 | 激情在线网站 | 日韩精品中文字幕在线不卡尤物 | 日韩综合视频在线观看 | 久久69精品久久久久久久电影好 | 国产成人精品在线 | 国产亚洲综合精品 | 久草视频免费在线播放 | 亚洲干| 狠狠狠色丁香综合久久天下网 | 亚洲精品网址在线观看 | 99re8这里有精品热视频免费 | 国产在线a | 国产手机免费视频 | 69亚洲乱 | 青青河边草手机免费 | 欧美一级片免费在线观看 | 99热这里精品 | 亚洲伊人色 | 成人av动漫在线 | 国产成人精品国内自产拍免费看 | 激情综合网婷婷 | 91av亚洲 | 精品国产91亚洲一区二区三区www | 国产精品综合久久久 | 中文 一区二区 | 欧美亚洲一区二区在线 | 亚洲欧洲精品一区二区 | 亚洲永久精品国产 | 欧美调教网站 | 97国产精品亚洲精品 | 久久国产精品视频免费看 | 国产精品综合av一区二区国产馆 | 911精品视频 | 中文字幕网站视频在线 | 日韩欧美精品一区二区三区经典 | 色视频网站在线 | 国产黄色免费电影 | 成年人视频在线观看免费 | 欧美久草视频 | 中文字幕在线电影 | 911精品美国片911久久久 | 久久久久久久看片 | 97视频免费在线 | 久久成人18免费网站 | 一区二区三区四区精品视频 | 欧美大片www | 欧美日韩一区二区在线观看 | 91字幕| 成人免费在线播放视频 | 精品在线不卡 | 久久国产精彩视频 | 天天射综合| 九九热.com| 欧美性爽爽 | 西西444www大胆无视频 | 丁香五月亚洲综合在线 | 亚洲v精品| 国产对白av | 亚洲精品国产综合久久 | 91av观看| 国产午夜精品一区 | 久久精品理论 | 4hu视频 | 九色在线视频 | 激情婷婷亚洲 | 亚洲成人精品在线 | 91av蜜桃 | 在线观看av的网站 | 99久热精品 | 色噜噜在线观看视频 | 久久精品高清视频 | 日韩字幕 | 久久99久久99精品免观看软件 | 91精品国产一区二区三区 | av 一区二区三区 | 日韩精品第1页 | 亚洲免费国产视频 | 欧美日韩视频观看 | 国产在线精品区 | 最新国产一区二区三区 | 色成人亚洲 | 国产麻豆剧传媒免费观看 | 成人小视频在线观看免费 | 国产成人精品一区二区三区免费 | 国产精品久久久久久久久久久杏吧 | 天天干天天做 | 在线看黄色的网站 | 国产日韩欧美在线观看 | 天天干亚洲 | 国产精品久久久久久吹潮天美传媒 | 天天干天天射天天爽 | 欧美精品中文在线免费观看 | 国产97视频在线 | 午夜精品久久久久久中宇69 | 综合精品久久久 | 久热国产视频 | 亚洲三级视频 | 国色天香在线 | 在线观看岛国片 | 胖bbbb搡bbbb擦bbbb | 久久 亚洲视频 | 婷婷国产精品 | 日本资源中文字幕在线 | 美女亚洲精品 | 2023国产精品自产拍在线观看 | 午夜精品久久久久99热app | 激情五月婷婷综合网 | 久久99免费观看 | 日韩电影一区二区三区在线观看 | www.亚洲在线| 夜夜爽www | 欧美精品九九99久久 | 2021国产精品 | 久久免费福利视频 | 97av免费视频 | 亚洲欧洲在线视频 | 亚洲精品国久久99热 | 欧美人人 | 99在线视频播放 | 五月婷婷导航 | 国产精品色婷婷 | 福利片视频区 | 国产视频综合在线 | 高清不卡免费视频 | 久久精品99国产国产精 | 国产精品久久久久免费 | 日韩久久久 | 精品在线视频一区 | av高清在线观看 | 日日爽天天爽 | 日韩视频www | 91精品国产高清 | 女女av在线 | 青青河边草观看完整版高清 | 亚洲丁香久久久 | 久久国产精品网站 | 欧美成年人在线视频 | 国产精品久久久久久久久久久不卡 | 亚洲欧洲日韩在线观看 | 四虎在线免费视频 | 亚洲电影网站 | 福利一区二区三区四区 | 又黄又刺激又爽的视频 | 久久久久免费观看 | 国产理论影院 | 99久久99久久精品国产片 | 三级av黄色 | 亚洲综合视频在线播放 | 国产精品18久久久久久久久久久久 | 亚洲国产精品第一区二区 | 国产精品网址在线观看 | 国产成人福利在线观看 | 九九电影在线 | 婷婷丁香激情五月 | 国产精品 日韩 欧美 | 久久久亚洲精华液 | 啪啪午夜免费 | 六月丁香在线观看 | 免费观看的av | 日韩精品一区二区三区免费观看视频 | 国产国语在线 | 久久综合给合久久狠狠色 | 精品久久久久久久久亚洲 | 爱情影院aqdy鲁丝片二区 | 黄色一级动作片 | 亚洲成av人电影 | 国产淫片 | 国产 日韩 欧美 在线 | 婷婷久月 | 一区二区三区韩国免费中文网站 | 成人看片| 免费高清在线一区 | 97人人澡人人爽人人模亚洲 | 午夜视频免费 | 99精品视频免费 | 91av中文字幕 | 91夫妻自拍 | 日韩精品中文字幕av | www在线免费观看 | 欧美色噜噜 | 96亚洲精品久久久蜜桃 | 五月婷婷影院 | 99精品在线免费在线观看 | 91精品欧美一区二区三区 | 久久久精品高清 | 中文字幕在线免费看 | 色99之美女主播在线视频 | 在线看成人 | 成人久久久精品国产乱码一区二区 | 久青草视频在线观看 | 97精品国产一二三产区 | 久久久久免费看 | 97人人人人 | 国产丝袜美腿在线 | 91精品入口 | 天天操天天操天天爽 | 国产中文a | 欧美大香线蕉线伊人久久 | 99精品国产视频 | 亚洲精品乱码久久久久久蜜桃欧美 | 综合激情网 | 久久精品视频2 | 免费在线视频一区二区 | 久久综合久久综合久久 | 国产精品黄色影片导航在线观看 | 在线播放视频一区 | 亚洲国产精品电影 | 九九热视频在线播放 | 黄色aa久久 | 免费一级片在线 | 在线观看日韩国产 | 欧美做受高潮电影o | 99色99| 国产成人精品久久亚洲高清不卡 | 国产精品视频专区 | 人人爽人人干 | 男女靠逼app | 久爱精品在线 | 免费视频黄色 | 中文在线免费一区三区 | 日韩一区二区三区在线观看 | 国产高清视频免费 | 国产小视频网站 | 国产一二三四在线观看视频 | 狠狠色丁香久久综合网 | 成年人网站免费观看 | 日韩欧美成 | 久久精品91视频 | 日韩午夜电影院 | 全久久久久久久久久久电影 | 午夜影院在线观看18 | 亚洲精品在线看 | av片免费播放 | 丁香婷婷综合五月 | 超碰97人人爱 | 免费毛片aaaaaa | 色婷婷激情电影 | 亚洲欧美视频在线播放 | 91在线91| 国产日韩欧美视频在线观看 | 中文字幕在线影视资源 | 久久一线| 天天综合网 天天 | 国产福利91精品一区二区三区 | 中文字幕在线观看免费高清完整版 | 色欧美成人精品a∨在线观看 | 3d黄动漫免费看 | 亚洲激情视频在线观看 | 久久国产精品影片 | 国产色在线,com | 日本黄色a级大片 | 精品国产欧美一区二区 | 手机在线观看国产精品 | 99久久综合国产精品二区 | 国产电影一区二区三区四区 | 免费日韩视频 | 日韩a级黄色 | 日日夜夜精品 | 中文字幕视频网 | 日韩午夜在线播放 | 精品久久久久久久久久国产 | 欧美日韩免费一区二区三区 | 天堂在线视频免费观看 | 久久免费精品 | 黄色三级视频片 | 免费在线一区二区 | 91超在线 | 亚洲三级国产 | 欧美一区二区三区特黄 | 精品国产一区二区三区免费 | 丁香婷婷久久久综合精品国产 | 国产尤物视频在线 | 精品国产乱码久久久久久久 | 亚洲国产97在线精品一区 | 国产精品视频在线观看 | 日韩av在线影视 | 狠色在线| 黄网站免费久久 | 日韩xxx视频 | av在线永久免费观看 | 91在线porny国产在线看 | 亚洲第一av在线播放 | 精品国产伦一区二区三区免费 | 欧美在线视频精品 | 中文字幕精品一区久久久久 | 欧美日本高清视频 | 麻豆一区在线观看 | 国产精品va最新国产精品视频 | 亚洲精品乱码久久久久久蜜桃91 | 日韩精品一区二区三区在线播放 | 在线天堂视频 | 人人干97 | 欧美亚洲xxx | 欧美久久久久久久久久久久久 | 毛片3| 欧美在线视频第一页 | 中文国产在线观看 | 国内精品视频一区二区三区八戒 | 性日韩欧美在线视频 | 国产精品电影在线 | 手机av在线网站 | 婷婷日日 | 国内精品视频免费 | 国产精品wwwwww| 午夜成人免费影院 | 欧美精品中文在线免费观看 | 成年人网站免费在线观看 | 日韩av免费在线电影 | 久久国产精品一二三区 | 天天操天天综合网 | 日本不卡一区二区三区在线观看 | 国产九九精品视频 | 在线观看av免费 | 国产高清一级 | 久热免费 | 精品成人久久 | 婷婷av电影| 精品婷婷 | 亚洲一区av| 亚洲精品美女久久久 | 日本午夜在线亚洲.国产 | 狠狠色综合网站久久久久久久 | av不卡在线看 | 亚洲视频axxx | 国产1区2区| 日日夜夜中文字幕 | 精品久久五月天 | 亚洲午夜久久久久 | 在线天堂中文www视软件 | 久久av福利| 999视频在线播放 | 欧美午夜a | 色婷婷狠狠18 | 国产黄色片免费看 | 热久久视久久精品18亚洲精品 | 在线观看黄网站 | 视频一区在线播放 | 久久久久久高潮国产精品视 | 少妇性xxx| 天堂入口网站 | 亚洲 欧美 日韩 综合 | 久久久久日本精品一区二区三区 | 免费黄色网址网站 | 最新99热| 国产成人99久久亚洲综合精品 | 五月天免费网站 | 在线播放 日韩专区 | 国产91影院 | 成人黄色大片网站 | 久久歪歪 | 亚洲黄色成人 | 国产精品久久麻豆 | 又湿又紧又大又爽a视频国产 | 国产成人一区在线 | 亚洲国产精品电影 | av在线免费在线观看 | 国内综合精品午夜久久资源 | 9在线观看免费高清完整 | 九月婷婷综合网 | 播五月综合| 麻豆视频免费在线播放 | 国产一级一片免费播放放 | 久久免费av电影 | 97免费在线观看视频 | 国产啊v在线 | 中文字幕亚洲高清 | 麻豆影视在线播放 | 在线观看视频一区二区 | 999免费视频 | 亚洲最新在线视频 | 久久久久亚洲国产 | 久久久综合九色合综国产精品 | 国产成人精品999 | 国产中文| 婷婷色狠狠| 色国产在线| 欧美做受高潮1 | 狠狠操电影网 | 欧美 日韩 成人 | 91精品少妇偷拍99 | 久久图| 亚洲国产精品99久久久久久久久 | 天天干天天草天天爽 | 在线日韩视频 | 99色亚洲 | 视频一区二区三区视频 | 欧美福利视频一区 | 996久久国产精品线观看 | 特级西西444www高清大视频 | 婷婷激情五月 | 久久久亚洲麻豆日韩精品一区三区 | 成人在线视频观看 | 五月综合色婷婷 | 成人av免费播放 | 美女视频黄免费 | 久久久免费看片 | 天天干天天搞天天射 | 日韩av在线影视 | 午夜av在线电影 | 免费在线观看av电影 | 免费福利在线播放 | 国产精品久久久久久久久久尿 | 欧美a√在线 | 国产精品四虎 | 久久天天躁狠狠躁夜夜不卡公司 | 亚洲在线不卡 | 中文字幕av电影下载 | 黄色三级免费 | 亚洲一级片在线观看 | 天天爽天天爽天天爽 | 久久国产二区 | 99视频这里只有 | 日韩视频免费观看高清完整版在线 | 91精品久久久久久综合乱菊 | 成人欧美在线 | 久久国产影院 | 免费色视频在线 | 国产精品a成v人在线播放 | 天天干天天做天天操 | 久久一二三四 | 亚洲电影成人 | 青春草视频在线播放 | 国产一级二级三级在线观看 | 免费一级黄色 | 免费一级毛毛片 | 婷婷色网站 | 99999精品| 色爱成人网| 激情久久伊人 | 久久久久国产精品厨房 | 色综合久久精品 | 91九色最新 | av中文字幕亚洲 | 在线观看免费国产小视频 | 欧美日韩免费视频 | 婷婷精品国产欧美精品亚洲人人爽 | 中文字幕在线免费看线人 | 久久久免费看视频 | 欧美一区二区在线免费观看 | 国产精品久久久久一区二区三区共 | 免费看搞黄视频网站 | 久久久精品日本 | 国产精品一区二区在线看 | 奇米先锋 | 黄色资源在线 | 亚洲黄色在线观看 | 丰满少妇在线观看网站 | 亚洲网站在线 | 99人久久精品视频最新地址 | 911久久 | 日产乱码一二三区别免费 | 伊人看片| 国产美女视频免费观看的网站 | 色播五月激情综合网 | 午夜免费电影院 | 中文字幕欧美激情 | 国产人在线成免费视频 | 国产精品专区h在线观看 | 久久久精品日本 | 久草精品网 | 国产四虎在线 | 狠狠狠狠狠色综合 | 国产免费视频一区二区裸体 | 中国一级特黄毛片大片久久 | 天天操比| 天天操偷偷干 | 麻豆传媒视频在线播放 | 亚洲aaa毛片 | 午夜av网站| 国产剧情一区在线 | 久久美女高清视频 | 全久久久久久久久久久电影 | 国产视频一区二区三区在线 | 伊人伊成久久人综合网小说 | 91激情视频在线观看 | 香蕉视频在线网站 | 日韩高清不卡在线 | 成人毛片在线观看视频 | 久久这里只有精品1 | 国产精品视频永久免费播放 | 亚洲九九爱| a√天堂中文在线 | 国产亚洲片 | 高清av中文在线字幕观看1 | av网站在线免费观看 | 欧美日韩一区二区在线 | 日韩精品一区二区在线观看 | 国产一线二线三线性视频 | 亚洲国产中文在线观看 | 国产色视频一区二区三区qq号 | 六月丁香综合 | 亚洲欧洲精品在线 | 成人免费在线播放 | 日韩在线观看中文字幕 | 美女视频国产 | 久久久久久毛片精品免费不卡 | 国产裸体bbb视频 | 欧美激情精品久久久久 | 91精品成人| 亚洲妇女av | 日本黄色大片儿 | www..com黄色片 | 欧美久久综合 | 久久狠狠亚洲综合 | 亚洲香蕉在线观看 | 久久黄色免费视频 | 美女搞黄国产视频网站 | 片黄色毛片黄色毛片 | 中文资源在线播放 | 91精品在线视频 | 97超碰资源 | 天天天色综合a | 久久免费片 | 久久久av免费 | 久久精品99国产精品亚洲最刺激 | 国产高清不卡一区二区三区 | 又污又黄的网站 | av电影免费在线播放 | 肉色欧美久久久久久久免费看 | 波多野结衣视频一区二区三区 | 日韩欧美极品 | 久久伊人爱 | 国产伦理久久精品久久久久_ | 成人午夜精品 | 这里只有精品视频在线观看 | 91视频免费看片 | www.久艹 | 久久综合色播五月 | 91丨九色丨高潮丰满 | 成年人免费在线观看网站 | 中文字幕在线国产精品 | 久久国产精品一区二区三区 | 日韩素人在线观看 | 高潮毛片无遮挡高清免费 | 久草视频中文在线 | 黄网站免费大全入口 | 高清在线一区二区 | 丁香婷婷成人 | 六月天综合网 | 亚洲国产网站 | 在线精品视频免费观看 | 欧美日韩一区二区视频在线观看 | 夜夜操狠狠干 | 亚洲视频1区2区 | 中文字幕国语官网在线视频 | 国产色拍拍拍拍在线精品 | 91字幕| 免费h视频| 国产精品男女 | aaa毛片视频 | 精品999 | 欧美日韩xxx| 亚洲成人国产精品 | 免费成人黄色 | av先锋影音少妇 | 天天操天天摸天天爽 | 开心丁香婷婷深爱五月 | 一区二区三区在线观看免费 | 麻豆国产在线视频 | 国产夫妻自拍av | 91原创在线观看 | 精品日本视频 | 国产一区不卡在线 | 四虎天堂| 六月丁香婷婷久久 | 亚在线播放中文视频 | 日韩欧美在线中文字幕 | 国产一级黄色av | 久久99精品久久只有精品 | 久久久官网 | 亚洲视频免费 | 亚洲高清国产视频 | av片在线观看 | 日韩在线观看小视频 | 亚洲精品视频国产 | 亚洲涩涩一区 | 婷婷丁香自拍 | 最新超碰在线 | 六月丁香婷 | 91中文字幕网 | 亚洲精品一区二区18漫画 | 正在播放 久久 | 中文字幕av一区二区三区四区 | 国产特黄色片 | 国产精品久久久久久一区二区 | 免费黄色av电影 | 精品在线二区 | 人成午夜视频 | 四虎影视成人精品国库在线观看 | 五月婷婷色综合 | 午夜精品一区二区三区在线观看 | 久久亚洲成人网 | 黄色a在线观看 | 蜜臀久久99精品久久久久久网站 | 国产精品高清在线观看 | 97精品伊人| 国产色在线,com | 久久久久久久久久久久久久免费看 | 久久96国产精品久久99软件 | 97色国产 | 中文字幕成人在线观看 | 中文字幕av全部资源www中文字幕在线观看 | 国产裸体bbb视频 | 狠狠婷婷 | 婷婷午夜 | 亚洲一区二区三区四区精品 | 九热在线| 久久久久国产成人精品亚洲午夜 | 久久免费毛片 | 日韩中文字 | 欧美性粗大hdvideo | 狠狠干免费 | 成年人视频在线免费播放 | 少妇精品久久久一区二区免费 | 欧美一级片在线播放 | 99视频+国产日韩欧美 | 丁香5月婷婷 | 超碰在线官网 | 99午夜| 中文字幕在线观看91 | 免费观看91| 在线免费看黄网站 | av在线电影播放 | 久久不卡视频 | 亚洲韩国一区二区三区 | 激情久久久久久久久久久久久久久久 | 激情综合五月天 | aaa日本高清在线播放免费观看 | 亚洲欧洲成人精品av97 | 99精品欧美一区二区 | 精品v亚洲v欧美v高清v | 国产一区高清在线 |