国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

跨端技術(shù)的本質(zhì)是什么?現(xiàn)狀如何?

共 9775字,需瀏覽 20分鐘

 ·

2022-03-08 09:28

來自團(tuán)隊 匡凌熙 同學(xué)的分享

零、何為跨端

write once, run everywhere

一次編寫,四處運(yùn)行就是跨端的真諦。因為前端當(dāng)下需要處理的場景實在是太多了:android、ios、pc、小程序,甚至智能手表、車載電視等,當(dāng)某幾個場景非常相似的時候,我們希望能夠用最少的開發(fā)成本來達(dá)到最好的效果,而不是每個端都需要一套單獨的人力來進(jìn)行維護(hù),所以跨端技術(shù)就誕生了。

那么在跨端方案百花齊放的今天,比如現(xiàn)在最為人們所熟知的react native、flutterelectron等,他們之間有沒有什么共同的特點,而我們又是否能夠找到其中的本質(zhì),就是今天這篇文章想講述的問題。

一、主流跨端實現(xiàn)方案

1.1 h5 hybrid 方案

其實,瀏覽器本就是一個跨端實現(xiàn)方案,因為你只需要輸入網(wǎng)址,就能在任何端的瀏覽器上打開你的網(wǎng)頁。那么,如果我們把瀏覽器嵌入 app 中,再將地址欄等內(nèi)容隱藏掉,是不是就能將我們的網(wǎng)頁嵌入原生 app 了。而這個嵌入 app 的瀏覽器,我們把它稱之為 webview ,所以只要某個端支持 webview ,那么它就能使用這種方案跨端。

同時這也是開發(fā)成本最小的一種方案,因為這實際上就是在寫前端界面,和我們開發(fā)普通的網(wǎng)頁并沒有太大區(qū)別。

1.2 框架層+原生渲染

典型的代表是 react-native,它的開發(fā)語言選擇了 js,使用的語法和 react 完全一致,其實也可以說它就是 react,這就是我們的框架層。而不同于一般 react 應(yīng)用,它需要借助原生的能力來進(jìn)行渲染,組件最終都會被渲染為原生組件,這可以給用戶帶來比較好的體驗。

1.3 框架層+自渲染引擎

這種方案和上面的區(qū)別就是,它并沒有直接借用原生能力去渲染組件,而是利用了更底層的渲染能力,自己去渲染組件。這種方式顯然鏈路會比上述方案的鏈路跟短,那么性能也就會更好,同時在保證多端渲染一致性上也會比上一種方案更加可靠。這類框架的典型例子就是 flutter

1.4 另類跨端

眾所周知,在最近幾年有一個東西變得非?;鸨盒〕绦?,現(xiàn)在許多大廠都有一套自己的小程序?qū)崿F(xiàn),但相互之間還是有不小差異的,通??梢越柚?taroremax 這類框架實現(xiàn)一套代碼,多端運(yùn)行的效果,這也算是一種另類的跨端,它的實現(xiàn)方式還是比較有意思的,我們后面會展開細(xì)講。

二、react-native 實現(xiàn)

2.1 rn的三個線程

rn 包含三個線程:

  • native thread:主要負(fù)責(zé)原生渲染和調(diào)用原生能力;
  • js thread:JS 線程用于解釋和執(zhí)行我們的js代碼。在大多數(shù)情況下,react native 使用的js引擎是JSC(JavaScriptCore) ,在使用 chrome 調(diào)試時,所有的 js 代碼都運(yùn)行在 chrome中,并且通過 websocket與原生代碼通信。此時的運(yùn)行環(huán)境是v8

  • shadow thread:要渲染到界面上一個很重要的步驟就是布局,我們需要知道每個組件應(yīng)該渲染到什么位置,這個過程就是通過yoga去實現(xiàn)的,這是一個基于flexbox的跨平臺布局引擎。shadow thread 會維護(hù)一個 shadow tree來計算我們的各個組件在 native 頁面的實際布局,然后通過 bridge 通知native thread 渲染 ui

2.2 初始化流程

  1. native 啟動一個原生界面,比如android會起一個新的activity來承載rn,并做一些初始化的操作。
  2. 加載 js 引擎,運(yùn)行 js 代碼,此時的流程和 react 的啟動流程就非常相似了,我們先簡單觀察調(diào)用棧,

是不是看見了一些非常熟悉的函數(shù)名,在上一講的基本原理中已經(jīng)提到過了,這里我們就不再贅述。同時再看一下FiberNode的結(jié)構(gòu),也和react的保持一致,只不過我們在js層是無法拿到真實結(jié)點的,所以stateNode只是一個代號。

  1. js 線程通知shadow thread。在react中,走到createInstance以后我們就可以直接調(diào)用createElement來創(chuàng)建真實結(jié)點了,但是在rn中我們沒辦法做到這一步,所以我們會通知native層讓它來幫助我們創(chuàng)建一個對應(yīng)的真實結(jié)點。
  1. shadow thread 計算布局,通知native Thread 創(chuàng)建原生組件。
  2. native 在界面上渲染原生組件,呈現(xiàn)給用戶。

2.3 更新流程

比如某個時候,用戶點擊了屏幕上的一個按鈕觸發(fā)了一個點擊事件,此時界面需要進(jìn)行相應(yīng)的更新操作。

  1. native 獲取到了點擊事件,傳給了js thread
  2. js thread根據(jù) react 代碼進(jìn)行相應(yīng)的處理,比如處理 onClick 函數(shù),觸發(fā)了 setState。
  3. react 的更新流程一樣,觸發(fā)了 setState 之后會進(jìn)行 diff,找到需要更新的結(jié)點
  4. 通知 shadow thread
  5. shadow thread 計算布局之后通知 native thread 進(jìn)行真正的渲染。

2.4 特點

我們上述說的通知,都是通過 bridge 實現(xiàn)的,bridge本身是用實現(xiàn)C++的,就像一座橋一樣,將各個模塊關(guān)聯(lián)起來,整個通信是一個「異步」的過程。這樣做好處就是各自之間不會有阻塞關(guān)系,比如 不會native thread因為js thread而阻塞渲染,給用戶良好的體驗。但是這種「異步」也存在一個比較明顯的問題:因為通信過程花費的時間比較長,所以在一些時效性要求較高場景上體驗較差。

比如長列表快速滾動的時候或者需要做一些跟手的動畫,整個過程是這樣的:

  1. native thread監(jiān)聽到了滾動事件,發(fā)送消息通知js thread
  2. js thread 處理滾動事件,如果需要修改 state 需要經(jīng)過一層js diff,拿到最終需要更新的結(jié)點
  3. js thread 通知 shadow thread
  4. shadow thread 通知 native 渲染

當(dāng)用戶操作過快的時候,就會導(dǎo)致界面來不及更新,進(jìn)而導(dǎo)致在快速滑動的時候會出現(xiàn)白屏、卡頓的現(xiàn)象。

2.5 優(yōu)化

我們很容易看出,這是由rn的架構(gòu)引出的問題,其實小程序的架構(gòu)也會有這個問題,所以在rn和小程序上出現(xiàn)一些需要頻繁通信的場景時,就會導(dǎo)致頁面非常差,流暢度降低。那么如果想解決這個問題,勢必要從架構(gòu)上去進(jìn)行修改。

三、從rn看本質(zhì)

那么既然我們知道了rn是如何實現(xiàn)的跨端,那么我們就可以來探究一下它本質(zhì)上是在干什么。首先,跨端可以分為「邏輯跨端」「渲染跨端」

「邏輯跨端」通常通過 vm來實現(xiàn),例如利用 v8 引擎,我們就能在各個平臺上運(yùn)行我們的 js 代碼,實現(xiàn)「邏輯跨端」

那么第二個問題就是「渲染跨端」,我們把業(yè)務(wù)代碼的實現(xiàn)抽象為開發(fā)層,比如 react-native 中我們寫的 react 代碼就屬于開發(fā)層,再把具體要渲染的端稱為渲染層。作為開發(fā)層來說,我一定知道我想要的ui長什么樣,但是我沒有能力去渲染到界面上,所以當(dāng)我聲明了一個組件之后,我們需要考慮的問題是如何把我想要什么告訴渲染層。

就像這樣的關(guān)系,那么我們最直觀的方式肯定是我能夠?qū)崿F(xiàn)一種通信方式,在開發(fā)層將消息通知到各個系統(tǒng),再由各個系統(tǒng)自己去調(diào)用對應(yīng)的 api 來實現(xiàn)最終的渲染。

function?render()?{
????if(A)?{
????????message.sendA('render',?{?type:?'View'?})
????}
????
????
????if(B)?{
????????message.sendB('render',?{?type:?'View'?})
????}
????
????
????if(C)?{
????????message.sendC('render',?{?type:?'View'?})
????}
}

比如這樣,我就能通過判斷平臺來通知對應(yīng)的端去渲染View組件。這一部分的工作就是跨端框架需要幫助我們做的,它可以把這一步放到 JS 層,也可以把這一步放到c++ 層。我們應(yīng)該把這部分工作盡量往底層放,也就是我們可以對各個平臺的 api 進(jìn)行一層封裝,上層只負(fù)責(zé)調(diào)用封裝的 api,再由這一層封裝層去調(diào)用真正的 api。因為這樣可以復(fù)用更多的邏輯,否則像上文中我們在 JS 層去發(fā)送消息給不同的平臺,我們就需要在A\B\C三個平臺寫三個不同方法去渲染組件。

但是,歸根結(jié)底就是,一定有一個地方是通過判斷不同平臺來調(diào)用具體實現(xiàn),也就是下面這樣

有一個地方會對系統(tǒng)進(jìn)行判斷,再通過某種通信方式通知到對應(yīng)的端,最后執(zhí)行真正的方法。其實,所有跨端相關(guān)操作其實都在做上圖中的這些事情。所有的跨端也可以總結(jié)為下面這句話:

「我知道我想要什么,但是我沒有能力去渲染,我要通知有能力渲染的人來幫助我渲染」

比如hybrid跨端方案中,webview其實就充當(dāng)了橋接層的角色,createElement,appendChildapi就是給我們封裝好的跨平臺api,底層最終調(diào)用到了什么地方,又是如何渲染到界面上的細(xì)節(jié)都被屏蔽掉了。所以我們利用這些api就能很輕松的實現(xiàn)跨端開發(fā),寫一個網(wǎng)頁,只要能夠加載 webview 的地方,我們的代碼就能跑在這個上面。

又比如flutter的方案通過研發(fā)一個自渲染的引擎來實現(xiàn)跨端,這種思路是不是相當(dāng)于另外一個瀏覽器?但是不同的點在于 flutter 是一個非常新的東西,而 webview 需要遵循大量的 w3c 規(guī)范和背負(fù)一堆歷史包袱。flutter 并沒有什么歷史包袱,所以它能夠從架構(gòu),設(shè)計的方面去做的更好更快,能夠做更多的事情。

四、跨端目前有什么問題

4.1 一致性

對于跨端來說,如何屏蔽好各端的細(xì)節(jié)至關(guān)重要,比如針對某個端特有的api如何處理,如何保證渲染細(xì)節(jié)上各個端始終保持一致。如果一個跨端框架能夠讓開發(fā)者的代碼里面不出現(xiàn) isIosisAndroid的字眼,或者是為了兼容各種奇怪的渲染而產(chǎn)生的非常詭異的hack方式。那我認(rèn)為它絕對是一個真正成功的框架。

但是按我經(jīng)驗而言,先后寫過的 h5、rn、小程序,他們都沒有真正做到這一點,所以項目里面會出現(xiàn)為了解決不同端不一致問題而出現(xiàn)的各種奇奇怪怪的代碼。而這個問題其實也是非常難解決的,因為各端的差異還是比較大的,所以說很難去完全屏蔽這些細(xì)節(jié)。

比如說h5中磨人的垂直居中問題,我相信只要開發(fā)過移動端頁面的都會遇見,就不用我多說了。

4.2 為什么出現(xiàn)了這么多框架

為什么大家其實本質(zhì)上都是在干一件事情,卻出現(xiàn)了這么多的解決方案?其實大家都覺得某些框架沒能很好的解決某個問題,所以想自己去造一套。其中可能很多開發(fā)者最關(guān)心的就是性能問題,比如:

  • rn因為架構(gòu)上的原因?qū)е履承﹫鼍靶阅懿睿运拖朕k法從架構(gòu)上去進(jìn)行修改。
  • flutter直接自己搞了一套渲染引擎,同時選用支持AOTdart作為開發(fā)語言。

但是其實我們在選擇框架的時候性能并不是唯一因素,開發(fā)體驗、框架生態(tài)這些也都是關(guān)鍵因素,我個人感受是,目前rn的生態(tài)還是比其他的要好,所以在開發(fā)過程中你想要的東西基本都有。

五、小程序跨端

ok,說了這么多,對于跨端部分的內(nèi)容其實我想說的已經(jīng)說的差不多了,還記得上文提到的 Taro、Uni-app 一類跨小程序方案么。為什么說它是另類的跨端,因為它其實并沒有實際跨端,只是為了解決各個小程序語法之間不兼容的問題。但是它又確實是一個跨端解決方案,因為它符合 「write once, run everything?!?/strong>

下面我們先來了解下小程序的背景。

5.1 什么是小程序

小程序是各個app廠商對外開放的一種能力。通過廠商提供的框架,就能在他們的app中運(yùn)行自己的小程序,借助各大app的流量來開展自己的業(yè)務(wù)。同時作為廠商如果能吸引到更多的人加入到開發(fā)者大軍中來,也能給app帶來給多的流量,這可以看作一個雙贏的業(yè)務(wù)。那么最終呈現(xiàn)在app中的頁面是以什么方式進(jìn)行渲染的呢?其實還是通過webview,但是會嵌入一些原生的組件在里面以提供更好的用戶體驗,比如video組件其實并不是h5 video,而是native video

5.2 什么是小程序跨端

那么到了這里,我們就可以來談一談關(guān)于小程序跨端的東西了。關(guān)于小程序跨端,核心并不是真正意義上的跨端,雖然小程序也做到了跨端,例如一份代碼其實是可以跑在androidIos上的,但是實際上這和hybrid跨端十分相似。

在這里我想說的其實是,市面上現(xiàn)在有非常多的小程序:字節(jié)小程序、百度小程序、微信小程序、支付寶小程序等等等等。雖然他們的dsl十分相似,但是終歸還是有所不同,那么就意味著如果我想在多個app上去開展我的業(yè)務(wù),我是否需要維護(hù)多套十分相似的代碼?我又能否通過一套代碼能夠跑在各種小程序上?

5.3 怎么做

想通過一套代碼跑在多個小程序上,和想通過一套代碼跑在多個端,這兩件事到底是不是一件事呢?我們再回到這張圖

這些平臺是否可以對應(yīng)上不同的小程序?

再回到那句話:「我知道我想要什么,但是我沒有能力去渲染,我要通知有能力渲染的人來幫助我渲染?!?/strong>

現(xiàn)在來理一下我們的需求:

  • 小程序的語法不好用,我希望用 react 開發(fā);
  • 我希望盡可能低的成本讓小程序跑在多個平臺上。

那么從這句話來看:「我」代表了什么,「有能力渲染的人」又代表了什么?

第二個很容易對應(yīng)上,「有能力渲染的人」就是小程序本身,只有它才能幫助我們把內(nèi)容真正渲染到界面上。

「我」又是什么呢?其實這個「我」可以是很多東西,不過這里我們的需求是想用react進(jìn)行開發(fā),所以我們回想一下第一講中react的核心流程,當(dāng)它拿到vdom的時候,是不是就已經(jīng)知道【我想要什么】了?所以我們把react拿到vdom之前的流程搬過來,這樣就能獲取到「我知道我想要什么」的信息,但是「我沒有能力去渲染」,因為這不是web,沒有dom api,所以我需要通知小程序來幫助我渲染,我還可以根據(jù)不同的端來通知不同的小程序幫助我渲染。

所以整個流程就是下面這樣的:

前面三個流程都在我們的js層,也就是開發(fā)層,我們寫的代碼經(jīng)歷一遍完整的 react 流程之后,會將最后的結(jié)果給到各個小程序,然后再走小程序自己的內(nèi)部流程,將其真正的渲染到界面上。

采用這種做法的典型例子有remaxtaro3,他們宣稱用真正的react去開發(fā)小程序,其實并沒有錯,因為真的是把react的整套東西都搬了過來,和react并無差異。我們用taro寫一個非常簡單的例子來看一下:

import?{?Component?}?from?'react'
import?{?View,?Text,?Button?}?from?'@tarojs/components'
import?'./index.css'


export?default?class?Index?extends?Component?{

??state?=?{
????random:?Math.random()
??}


??componentWillMount?()?{?}


??componentDidMount?()?{?}


??componentWillUnmount?()?{?}


??componentDidShow?()?{?}


??componentDidHide?()?{?}


??handleClick?=?()?=>?{
????debugger;
????console.log("Math.random()",?Math.random());
????this.setState({random:?Math.random()})
??}


??render?()?{
????return?(
??????<View?className='index'>
????????<Text>Hello?world!?{this.state.random}Text>

????????<Button?onClick={this.handleClick}>clickButton>
??????View>
????)
??}
}

這是一個用taro寫的組件,把它編譯到字節(jié)小程序之后是這樣的效果:

根據(jù)我們之前的分析,在最后生成的文件中,一定包含了一個「小程序渲染器」。它接受的data就是整個ui結(jié)構(gòu),然后通過小程序的渲染能力渲染到界面上,我們?nèi)?code style="overflow-wrap: break-word;margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 148, 247);background: rgba(59, 170, 250, 0.1);padding-right: 2px;padding-left: 2px;border-radius: 2px;height: 21px;line-height: 22px;">dist文件中找一下,就能找到一個base.ttml的文件,里面的內(nèi)容是這樣的

<template?name="taro_tmpl">
??<block?tt:for="{{root.cn}}"?tt:key="uid">
????<template?is="tmpl_0_container"?data="{{i:item}}"?/>
??block>
template>

<template?name="tmpl_0_catch-view">
??<view?hover-class="{{i.hoverClass===undefined?'none':i.hoverClass}}"?hover-stop-propagation="{{i.hoverStopPropagation===undefined?false:i.hoverStopPropagation}}"?hover-start-time="{{i.hoverStartTime===undefined?50:i.hoverStartTime}}"?hover-stay-time="{{i.hoverStayTime===undefined?400:i.hoverStayTime}}"?animation="{{i.animation}}"?bindtouchstart="eh"?bindtouchend="eh"?bindtouchcancel="eh"?bindlongpress="eh"?bindanimationstart="eh"?bindanimationiteration="eh"?bindanimationend="eh"?bindtransitionend="eh"?style="{{i.st}}"?class="{{i.cl}}"?bindtap="eh"?catchtouchmove="eh"??id="{{i.uid}}">
????<block?tt:for="{{i.cn}}"?tt:key="uid">
??????<template?is="tmpl_0_container"?data="{{i:item}}"?/>
????block>
??view>
template>

<template?name="tmpl_0_static-view">
??<view?hover-class="{{i.hoverClass===undefined?'none':i.hoverClass}}"?hover-stop-propagation="{{i.hoverStopPropagation===undefined?false:i.hoverStopPropagation}}"?hover-start-time="{{i.hoverStartTime===undefined?50:i.hoverStartTime}}"?hover-stay-time="{{i.hoverStayTime===undefined?400:i.hoverStayTime}}"?animation="{{i.animation}}"?style="{{i.st}}"?class="{{i.cl}}"??id="{{i.uid}}">
????<block?tt:for="{{i.cn}}"?tt:key="uid">
??????<template?is="tmpl_0_container"?data="{{i:item}}"?/>
????block>
??view>
template>

<template?name="tmpl_0_pure-view">
??<view?style="{{i.st}}"?class="{{i.cl}}"??id="{{i.uid}}">
????<block?tt:for="{{i.cn}}"?tt:key="uid">
??????<template?is="tmpl_0_container"?data="{{i:item}}"?/>
????block>
??view>
template>

<template?name="tmpl_0_view">
??<view?hover-class="{{i.hoverClass===undefined?'none':i.hoverClass}}"?hover-stop-propagation="{{i.hoverStopPropagation===undefined?false:i.hoverStopPropagation}}"?hover-start-time="{{i.hoverStartTime===undefined?50:i.hoverStartTime}}"?hover-stay-time="{{i.hoverStayTime===undefined?400:i.hoverStayTime}}"?animation="{{i.animation}}"?bindtouchstart="eh"?bindtouchmove="eh"?bindtouchend="eh"?bindtouchcancel="eh"?bindlongpress="eh"?bindanimationstart="eh"?bindanimationiteration="eh"?bindanimationend="eh"?bindtransitionend="eh"?style="{{i.st}}"?class="{{i.cl}}"?bindtap="eh"??id="{{i.uid}}">
????<block?tt:for="{{i.cn}}"?tt:key="uid">
??????<template?is="tmpl_0_container"?data="{{i:item}}"?/>
????block>
??view>
template>

<template?name="tmpl_0_static-text">
??<text?selectable="{{i.selectable===undefined?false:i.selectable}}"?space="{{i.space}}"?decode="{{i.decode===undefined?false:i.decode}}"?style="{{i.st}}"?class="{{i.cl}}"??id="{{i.uid}}">
????<block?tt:for="{{i.cn}}"?tt:key="uid">
??????<template?is="tmpl_0_container"?data="{{i:item}}"?/>
????block>
??text>
template>

<template?name="tmpl_0_text">
??<text?selectable="{{i.selectable===undefined?false:i.selectable}}"?space="{{i.space}}"?decode="{{i.decode===undefined?false:i.decode}}"?style="{{i.st}}"?class="{{i.cl}}"?bindtap="eh"??id="{{i.uid}}">
????<block?tt:for="{{i.cn}}"?tt:key="uid">
??????<template?is="tmpl_0_container"?data="{{i:item}}"?/>
????block>
??text>
template>

<template?name="tmpl_0_button">
??<button?size="{{i.size===undefined?'default':i.size}}"?type="{{i.type}}"?plain="{{i.plain===undefined?false:i.plain}}"?disabled="{{i.disabled}}"?loading="{{i.loading===undefined?false:i.loading}}"?form-type="{{i.formType}}"?open-type="{{i.openType}}"?hover-class="{{i.hoverClass===undefined?'button-hover':i.hoverClass}}"?hover-stop-propagation="{{i.hoverStopPropagation===undefined?false:i.hoverStopPropagation}}"?hover-start-time="{{i.hoverStartTime===undefined?20:i.hoverStartTime}}"?hover-stay-time="{{i.hoverStayTime===undefined?70:i.hoverStayTime}}"?name="{{i.name}}"?bindtouchstart="eh"?bindtouchmove="eh"?bindtouchend="eh"?bindtouchcancel="eh"?bindlongpress="eh"?bindgetphonenumber="eh"?data-channel="{{i.dataChannel}}"?style="{{i.st}}"?class="{{i.cl}}"?bindtap="eh"??id="{{i.uid}}">
????<block?tt:for="{{i.cn}}"?tt:key="uid">
??????<template?is="tmpl_0_container"?data="{{i:item}}"?/>
????block>
??button>
template>

<template?name="tmpl_0_scroll-view">
??<scroll-view?scroll-x="{{i.scrollX===undefined?false:i.scrollX}}"?scroll-y="{{i.scrollY===undefined?false:i.scrollY}}"?upper-threshold="{{i.upperThreshold===undefined?50:i.upperThreshold}}"?lower-threshold="{{i.lowerThreshold===undefined?50:i.lowerThreshold}}"?scroll-top="{{i.scrollTop}}"?scroll-left="{{i.scrollLeft}}"?scroll-into-view="{{i.scrollIntoView}}"?scroll-with-animation="{{i.scrollWithAnimation===undefined?false:i.scrollWithAnimation}}"?enable-back-to-top="{{i.enableBackToTop===undefined?false:i.enableBackToTop}}"?bindscrolltoupper="eh"?bindscrolltolower="eh"?bindscroll="eh"?bindtouchstart="eh"?bindtouchmove="eh"?bindtouchend="eh"?bindtouchcancel="eh"?bindlongpress="eh"?bindanimationstart="eh"?bindanimationiteration="eh"?bindanimationend="eh"?bindtransitionend="eh"?style="{{i.st}}"?class="{{i.cl}}"?bindtap="eh"??id="{{i.uid}}">
????<block?tt:for="{{i.cn}}"?tt:key="uid">
??????<template?is="tmpl_0_container"?data="{{i:item}}"?/>
????block>
??scroll-view>
template>

<template?name="tmpl_0_static-image">
??<image?src="{{i.src}}"?mode="{{i.mode===undefined?'scaleToFill':i.mode}}"?lazy-load="{{i.lazyLoad===undefined?false:i.lazyLoad}}"?style="{{i.st}}"?class="{{i.cl}}"??id="{{i.uid}}">
????<block?tt:for="{{i.cn}}"?tt:key="uid">
??????<template?is="tmpl_0_container"?data="{{i:item}}"?/>
????block>
??image>
template>

<template?name="tmpl_0_image">
??<image?src="{{i.src}}"?mode="{{i.mode===undefined?'scaleToFill':i.mode}}"?lazy-load="{{i.lazyLoad===undefined?false:i.lazyLoad}}"?binderror="eh"?bindload="eh"?bindtouchstart="eh"?bindtouchmove="eh"?bindtouchend="eh"?bindtouchcancel="eh"?bindlongpress="eh"?style="{{i.st}}"?class="{{i.cl}}"?bindtap="eh"??id="{{i.uid}}">
????<block?tt:for="{{i.cn}}"?tt:key="uid">
??????<template?is="tmpl_0_container"?data="{{i:item}}"?/>
????block>
??image>
template>

<template?name="tmpl_0_#text"?data="{{i:i}}">
??<block>{{i.v}}block>
template>

<template?name="tmpl_0_container">
??<template?is="{{'tmpl_0_'?+?i.nn}}"?data="{{i:i}}"?/>
template>

從名字可以看出,這是用于渲染各種組件的template,所以當(dāng)我們拿到react傳遞過來的data時,將其傳給template,template就能根據(jù)對應(yīng)的組件名采用不同的模版進(jìn)行渲染。隨后再用一個for循環(huán)將其子組件進(jìn)行遞歸渲染,完成整個頁面的渲染。這個就可以理解為我們針對不同端寫的不同渲染器,如果我們編譯到wx小程序,這里面的內(nèi)容是會不同的。

總之,「在」**react**「對其處理完之后,會把數(shù)據(jù)」**setData**「傳遞給「小程序」,小程序再用之前寫好的各種」**template**「將其渲染到頁面上?!?/strong>

下面這張圖就是經(jīng)過react處理之后,能夠拿到頁面的數(shù)據(jù),將其傳遞給小程序之后,就能遞歸渲染出來。

那么這樣的架構(gòu)有什么問題呢,可以很明顯的看到會走兩遍diff,為什么會走兩遍diff呢?因為在react層為了獲取到我想要什么這個信息,我們必須走一遍diff,這樣才能將最后得到的data交給小程序。

而交給小程序之后,小程序?qū)τ谥暗牧鞒淌菬o感知的,所以它為了得到需要更新什么這個信息,也需要過一遍diff,或者通過一些其他的方式來拿到這個信息(并沒有深入了解過小程序的渲染流程,所以不確定是否是通過diff拿到的),所以這一整套流程就會走兩遍diff。

為什么我們不能將兩次diff合并為一次?因為小程序的渲染對開發(fā)者而言就是個黑盒,我們不能干擾到其內(nèi)部流程。如果我們能夠直接對接小程序的渲染sdk,那么其實根本沒必要走兩遍diff,因為前置的 reactdiff我們已經(jīng)能夠知道需要更新什么內(nèi)容。

這個問題的本質(zhì)和普通意義上的跨端框架沒有太大的區(qū)別,開發(fā)層也就是 react 知道自己需要什么東西,但是它沒有能力去渲染到界面上,所以需要通過小程序充當(dāng)渲染層來渲染到真正的界面上。這種開發(fā)方式有一種用 react 去寫 vue 的意思,但是為什么會出現(xiàn)這種詭異的開發(fā)方式,如果這個 vue 做的足夠好的話,誰又想去這樣折騰?

5.4 組件的嵌套

其實還有一個小問題,wxtemplate是無法支持遞歸調(diào)用的,也就導(dǎo)致了我們想用template遞歸渲染data內(nèi)容是無法實現(xiàn)的,那么這個問題要如何解決呢..我們看一下上面的代碼在wx小程序中編譯出來的結(jié)果:

我們可以看到各種template之間多了0、1、2、3這種標(biāo)號..就是為了解決無法遞歸調(diào)用的問題,提前多造幾個名字不同功能相同的template,不就能跨過遞歸調(diào)用的限制了么...

六、另一種粗暴的跨端

上述的這些跨端都是通過某種架構(gòu)方式去實現(xiàn)的,那如果我們粗暴一點的想,我能不能直接把一套代碼通過編譯的方式去編譯到不同的平臺。比如我把js代碼編譯成java代碼、object-c代碼,其實,個人感覺也不是不行,但是因為這些的差異實在太大,所以在寫js代碼的時候,可能需要非常強(qiáng)的約束性、規(guī)范性,把開發(fā)者限制在某個區(qū)域內(nèi),才能很好的編譯過去。也就是說,從jsjava其實是一個自由度高到自由度低的一個過程,肯定是無法完全一一對應(yīng)上的,并且由于開發(fā)方式、語法完全不一樣,所以想通過編譯的方式將js編譯到iosandroid上去還是比較難的,但是對于小程序來說,嘗試把jsx編譯到template似乎是一個可行的方案,實際上,taro1/2 都是這么干的。不過從jsxtemplate也是一個自由度從高到低的一個過程,所以是沒辦法絕對完美地將把所有語法都編譯到template...

這里可以給大家分享一個很有意思的例子,最近很火的 SolidJS 框架也支持用 JSX 寫代碼,但是它完全沒有react這么重的runtime,因為它的JSX最終會被編譯成一些原生的操作...我們看一個簡單的例子:https://playground.solidjs.com/

react 語境下,我們在input框里面輸入內(nèi)容的時候,上面的文案應(yīng)該跟著改變,但是實際上并沒有。這是因為這個東西最后被編譯完之后是一些原生的操作,它其實只會運(yùn)行一遍,最后你觸發(fā)的各種click并不會導(dǎo)致函數(shù)重新運(yùn)行,而是直接通過原生操作操作到對應(yīng)的DOM上來修改視圖,也就導(dǎo)致了上面問題的產(chǎn)生。

其實我覺得這樣挺反人類的,雖然是JSX的語法,但是卻缺少了最核心的東西:函數(shù)式的思維。(還不如寫template)。

七、virtual dom

7.1 對于跨端的意義

提到跨端,可能很多人第一個想到的東西就是 virtual dom,因為它是對于ui的抽象,脫離了平臺,所以可能很多人會覺得virtual dom和跨平臺已經(jīng)是綁定在一起的東西了。但是其實個人感覺并不是。

首先我們回想一下,我們之前說到的跨平臺的本質(zhì)是什么?開發(fā)層知道自己想要什么,然后告訴渲染層自己想要什么,就這么簡單。那對于react-native來說,是通過virtual dom來判斷自己需要更新什么結(jié)點的嗎?其實并不是,單靠一個virtual dom還不足以獲取到這個信息,必須還要加上diff,所以是virtual dom+diff獲取到了自己想要什么的信息,再通過通信的方式告訴native去更新真正的結(jié)點。

所以virtual dom在這個里面只扮演了一個獲取方法的角色,是通過virtual dom+diff這個方法拿到了我們想要的東西。換言之,我們也可以通過其他的方法來拿到我們想要什么。比如之前分享的san框架,這是一個沒有virtual dom的框架,但是它為什么能夠跨平臺,我們先不管它內(nèi)部是如何實現(xiàn)的,但是在更新階段,如果它在某個時刻調(diào)用了 createElement,那么它一定是知道了:自己想要什么。對應(yīng)上跨端的內(nèi)容,這個時候就能通過某種手段去告訴native,渲染某個東西。

「所以,當(dāng)我們通過其他手段獲取到了:我們想要什么這個信息之后,就能通知」**native**「去渲染真正的內(nèi)容?!?/strong>

7.2 virtual dom的優(yōu)勢

那么vdom的優(yōu)勢在于什么地方?我認(rèn)為主要是下面兩個:

  1. 開創(chuàng)jsx新時代,函數(shù)式編程思想
  2. 強(qiáng)大的表達(dá)力。能夠使用template獲取更多優(yōu)化信息,又能夠支持 jsx

首先,jsx 簡直開創(chuàng)了一個新時代,讓我們能夠以函數(shù)式編程思想去寫ui,之前誰能想到一個切圖仔還能用這樣的方式去寫ui。

其次,我們知道,vue雖然是使用的template作為dsl,但是實際上我們也是可以寫jsx的,jsx所提供的靈活能力是template無法比擬的。而之所以能夠同時支持templatejsx其實就是因為vdom的存在,如果vue不引入vdom,是沒辦法說去支持jsx的語法的,或者說,是沒辦法去支持真正的jsx。

八、結(jié)語

還是那句話,跨端就是:「我知道我想要什么,但是我沒有能力去渲染,我要通知有能力渲染的人來幫助我渲染?!?/strong>

他們的本質(zhì)都非常簡單,但是細(xì)節(jié)卻非常難處理,同時對于目前市面上的多種跨端框架,也需要大家根據(jù)自己的項目去權(quán)衡利弊選擇一個最有方案,畢竟目前沒有一個框架能完全吊打所有其他框架,適合自己的才是最好的。

瀏覽 56
點贊
評論
收藏
分享

手機(jī)掃一掃分享

分享
舉報
評論
圖片
表情
推薦
點贊
評論
收藏
分享

手機(jī)掃一掃分享

分享
舉報

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 99re热| 九九热播精品| 中文字幕无码在线视频| 天天想夜夜操| 日韩三级精品| WWW黄片| 91成人免费视频| 91久久国产综合久| 国产精品久久久999| 欧美三级视频在线| 久久人妻无码中文字幕系列| 亚洲骚货| 色综合一区二区| 久久九九热| 国产熟女AV| 亚洲人内射片又| 99视频内射三四| 青娱乐伊人| 人人人人人人人人操| 999热这里只有精品| 久久大香蕉| 先锋影音资源av| 国产精品77777| 91在线视频免费| 日韩AV资源网| 午夜成人福利在线观看| 久久久一区二区三区四区免费听 | 精品国产AV色一区二区深夜久久| 黄色影视不卡| 亚洲高清在线视频| 欧美中文字幕在线视频| 99re这里| 亚洲一区翔田千里无码| 日本A一级片| 亚洲精品字幕久久久久| 伊人成人在线| 肏屄免费视频| 翔田AV无码秘三区| 亚洲天堂无码高清| 成人福利视频在线观看| 日本一级片免费看| 欧美激情伊人| 少妇无码中文| 插菊花综合| 国产精品九九| 亚洲AV高清| 超碰天天操| 在线观看视频无码| 午夜爱爱爱| 9久精品| 国产在线一二三| 国产中文| 久热在线视频| 亚洲欧美另类在线| 亚洲国产三级片| 国产乱伦内射| 欧一美一婬一伦一区二区三区黑人-亚| 无码高清视频在线观看| 免费日韩AV| 美国操逼片| 激情五月婷婷| 自拍偷拍亚洲| 久热网| 人人操综合| 无码无码无码| 特一级黄色视频| 亲孑伦XXXⅹ熟女| av影音先锋| 中文无码日韩| 操逼片| 美女被操免费网站| 成人一级视频| 狠狠撸在线观看| 日韩操B视频| 五月丁香六月婷婷综合| 亚州视频在线| 色天堂污| 午夜ww| 无码人妻AⅤ一区二区三区 | 国家一级A片| 大a片| 99国产精品99久久久久久| 99在线视频免费观看| 国产1区2区3区| 亚洲无码精品一区二区| 欧美亚洲动漫| 日本少妇做爱| 亚洲视频在线视频| 东京热91| 中文字幕北条麻妃在线| 俺来也听听婷婷| 你懂得在线视频| 欧美香蕉在线| 特黄特色一级特黄大片| 亚洲无码一区二区三区蜜桃| 国产精品无码久久久久成人app | 中文字幕一区二区三区四区五区六区| 北条麻妃被躁57分钟视频在线 | 国产在线观看一区二区| 一级片免费视频| 91成人电影在线| 久久伊人草| 国产Av高清| 深爱激情网五月天| 亚洲精品乱码久久久久久| 中文在线免费看视频| 日韩一级片免费| 青青操成人在线视频| 久久久久亚洲AV无码网影音先锋| 日韩毛片大全| 男人操女人免费网站| AV资源在线免费观看| 国产高清无码免费在线观看| 青娱乐在线精品| 特黄特色免费视频| 久久久久成人视频| 亚洲国产精品尤物yw在线观看| 韩国无码成人电影啊荒| 黄色电影地址| 午夜亚洲AⅤ无码高潮片苍井空| 无码在线播放视频| 成人免费啪啪视频| 熟女内射| 久久一二三| 六月激情丁香| 五月天婷婷成人| 欧美生活片18| 日韩第1页| 夜夜操天天日| 亚洲日韩成人在线| 亚洲AV无码国产综合专区| 麻豆AV无码| 青草视频在线免费观看| 日韩欧美成人视频| www.一区二区三区| 亚洲色图在线视频| 亚洲图片欧美色图| 五月丁香啪| 无码内射视频| 亚洲成人视频| 狼人社區91國產精品| 国产色秘乱码一区二区三区| 性饥渴欧美老妇XXXXX| 亚洲人成777| 免费观看黄色一级片| 五月天狠狠| 欧美老妇另类BBwBBw| 无码蜜桃一区二区| 丁香五月天天| 人人肏屄| 久久久久久97| 伊人成人大香蕉| 久久久久久久免费视频| 免费人妻视频| 特级丰满少妇一级AAAA爱毛片| 日日干干| 天天玩夜夜玩天天玩国产99| 女同一区二区三区| 亚洲色伦| 日韩一区二区高清无码| 好吊顶亚洲AV大香蕉色色| 日产精品久久久久| 大地影院资源官网| 色婷婷亚洲综合| 高清免费无码视频| 国产欧美熟妇另类久久久| 日韩中文字幕在线视频| 青草成人在线视频| www.777熟女人妻| 亚洲成人h| 日本韩国欧美18| 日韩操片| 韩国精品无码| 先锋影音AV在线| 西西444www| 婷婷五月天在线观看| 福利视频网亚洲| 亚洲精品国产精品乱码不卡√香蕉| 夜夜夜夜撸| 91三级片在线观看| 欧美午夜精品久久久久久3D| 免费黄片视频在线观看| 欧美猛交| 亚洲天堂自拍| 成人手机AV| 欧美成人免费精品| 免费在线观看无码| 日韩欧美成人网站| 日本久久网站| 日韩欧美黄色| 国产美女自拍| 艹逼逼视频| 免费黄色av网址| 欧美熟妇BBB搡BBB| aaa久久| 亚洲狼人综合| 黄片www| 亚洲精品一区中文字幕乱码| 91亚洲精华国产精华精华液| 影音先锋在线视频观看| 先锋成人在线| 日韩精品不卡| 国产成人视频| 中文在线最新版天堂8| 黄色成人大片| 黄a在线| 91免费高清视频| 日毛片| 中文字幕国产| 伊人综合干| 欧美日韩第一区| 北条麻妃毛片| 男人天堂v| 99re这里只有| 青青草99热| 成年人黄色视频| NP玩烂了公用爽灌满视频播放 | 最近日韩中文字幕中文翻译歌词| 兔子先生和優奈玩游戲脫衣服,運氣報表優奈輸到脫精光 | 亚洲永久| 色一本| 亚洲精品无码更新| 亚洲成人在线无码| 大香蕉手机在线视频| 欧美A级视频| 一本色道精品久久一区二区三区| 蜜桃AV在线观看| 亚洲日韩三级片| 欧美亚洲激情| 人人摸人人草| 五月婷婷中文版| 国产精品宾馆在线| 超碰99热| 欧美日韩成人在线| 日韩在线视频不卡| 九九热在线精品视频| 黄片无码免费观看| 国产一级特黄A片| 久久夜色精品噜噜亚洲AV| 九九美女视频| 久操亚洲| 一本一道久久| 大色欧美综合| 激情五月天开心网| 无码在线网站| 午夜激情视频| 亚洲AV秘一区二区色盗战流出| 91AV在线观看视频| 国产视频黄| 97精品综合久久| 久操视频一区二区三区| 亚洲丁香五月天| 国产做爱视频| 中文字幕亞洲高清手機版第617| 乳揉みま痴汉电车羽月希免费观看 | 毛片91| 搡BBB| 亚洲综合五月天| 日韩在线第—页| 精品A区| 国产一级a毛一级a爰片| 亚洲色情在线播放| 天堂网亚洲| 亚洲精品成人无码毛片| 天堂在线最新资源| 人妻丰满精品一区二区| 欧美激情另类| 另类一区| 7777精品伊人久久7777| 大香蕉在线伊人| 久草视频网站| 一二三区| 国产三级片无码| 日韩中文字幕有码| 奇米四色秒播| 国产一区一区| 哪里可以看毛片| 丰满人妻一区二区三区视频在线不卡 | 一区二区三区成人| 国产一精品一aⅴ一免费| 中文资源在线a中文| 久热无码| 微拍福利一区二区| 人人肏屄| 老欧性老太色HD大全| 青娱乐国产AV| 国产又爽又黄免费| 麻豆免费视频| 中文无码日本高潮喷水| 日本成人A片| 97资源超碰| 国产精品成人国产乱| 91大香蕉伊人| eeuss一区| 免费一级黄色毛片| 色婷婷av在线| 亚洲免费视频在线| 欧美性爱高清| 美日韩一区二区三区| 99在线视频免费观看| av黄色网| 欧美日韩成人一区二区三区| 露脸丨91丨九色露脸| 欧美后门菊门交4| 欧美特大黄| 欧美日韩激情| 五月天色婷婷丁香| 日韩a级毛片| 91精品在线播放| 免费在线观看AV片| 日韩熟妇无码中文字幕| 一级黄片学生妹| 日韩日韩日韩日韩| 国产91在线播放| 艹逼逼视频| 最近中文字幕在线中文字幕7| 亚洲影音| 91精品人妻一区二区三区四区 | 日韩精品人妻一区二区| 操人在线观看| 日韩中文字码无砖| 成人AV电影在线观看| 狠狠色噜噜狠狠狠7777| 蜜桃久久99精品久久久酒店| 免费观看黄色一级片| 日韩欧美v| 日欧美美女逼| 午夜福利电影AV| 不卡中文字幕| 日韩A级视频| 日韩啪啪网站| 91大神久久| 免费无码国产在线55| 影音先锋男人站| 玖玖国产精品| 中文字幕在线观看网址最新地址| 免费看欧美成人A片| 3d动漫精品一区二区三区在线观看 | 自拍一区在线观看| 久久久人妻熟妇精品无码蜜桃| 欧美精品在线观看| 婷婷国产成人精品视频| 99乱伦| 中文字幕一区二区三区人妻电影 | 四虎性爱视频| 久操| 人人搞人人操| 夜夜骚av一区二区三区| 久操免费在线观看| 大香蕉官网| 欧美成人五月天| 簧片网站在线观看| 九九热播精品| 国产做受91一片二片老头| 日韩操B| 蜜桃av无码一区三区| 影音先锋成人网| 91高潮久久久久久久| 一级黄色视频在线观看| 九月婷婷综合| 亚洲无码一级| 亚洲色成人中文字幕在线| AV在线免费观看网址| 成人免费无码毛片| 四色永久成人网站| 日韩另类| 午夜啊啊啊| 国产激情都市一区二区三区欧美| ww毛片| 亚洲AⅤ| 精产国品一区二区三区| 草逼com| 福利一区在线观看| 鸡巴网站| 免费无码婬片AAAA片在线蜜芽| 黄色毛片在线观看| 特黄无码| 免费一级电影| 一本一道久久综合| 日本一区二区不卡| 国产精品1区2区3区| 97久久精品国产熟妇高清网| 国产成人精品a视频一区| 国产丨熟女丨国产熟女视频| AV电影一区| 青青草99| 欧美色图俺去了| 国内自拍视频在线观看| 国产小视频在线免费观看| 人人插人人摸| 美女网站视频黄| 久久九| 日韩啊啊啊| 久久免费高清视频| 亚洲.无码.制服.日韩.中文字幕 | 黄片免费观看视频| 久久激情av| 亚洲第一福利视频| 一区二区三区久久久久| 18禁黄网站| 日韩av小电影| 综合色国产精品欧美在线观看| 亚洲中文字幕观看| 无套进入无套内谢| 亚洲色综合久久五月| 国产美女久久久| 2018天天干天天操| 久久久久久久极品内射| 2025中文字幕| 欧美日韩日逼视频| 免费黄色| 黄色草逼视频| 91麻豆福利在线观看| 北条麻妃无码一区二区| 欧美成人精品A片免费一区99| 91含羞草www·Com| 好屌肏| 九九视频免费在线观看| 啊啊啊啊啊靠逼| 国内精品一区二区| 婷婷综合亚洲| 永久免费不卡在线观看黄网站| 亚洲天堂第一页| 操逼免费观看视频| 黄色视频网站免费在线观看| 亚洲黄色Av| 日本黄色片| 亚洲午夜精品久久久| 乱子伦一区二区三区视频在线观看 | 免费成人AV| 在线观看国产一区| 人人人人摸| 无码视频免费看| 一插菊花网| 免费无码视频| 欧美伊人大香蕉| 久草a视频| 少妇搡BBBB搡BBB搡视频一级| 九热精品| 肏屄视频在线观看| 日韩欧美91| 91探花足浴店少妇在线| 欧美人操逼视频| 九九r在线精品观看视频| 日韩三级成人| 在线中文AV| 加勒比无码在线| 新版欧美内射大全| 成人免费无码毛片| 亚洲AV无码成人精品国产五月天| 少妇人妻一区二区三区| 91在线精品秘一区二区黄瓜| 日韩综合在线视频| 日韩AV一区二区在线观看| 日韩中文字幕有码| 中文字幕五码| 日韩99在线观看| 人妻丰满熟妇av无码区| 精品免费一区二区三区四区| 91精东传媒果冻传媒| 欧美视频a| 亚洲中文字幕免费观看视频| 黑人操逼视频| 国产男女视频| 91精品国际| 成人性爱AV| 国产农村妇女精品一二区| 青吴乐大香蕉| 欧美日韩性爱| 国内精品久久久久久久久久| 2025最新偷拍| 四川女人毛多水多A片| 草草影院CCYYCOM屁屁影院合集限制影院 | 欧美在线视频免费观看| 日本无码视频在线| 猫咪视频大全视频| 毛片一级片| 亚洲AV无码成人片在线| 蜜挑视频一区二区三区| 天堂国产| 亲子伦一区二区三区观看方式| 欧美丝袜脚交xxxxBH| 亚洲色一区二区| 天天天日天天天天天天天日歌词| www伦理片-韩国三级三级三级a三级-成人AV | 国产一级a毛一级做a爱| 91探花在线播放| 色天堂视频在线观看| 国产无码高潮在线| 亚洲一区欧美| 日本大香蕉在线视频| 成人精品一区二区三区| 黄页免费视频| 久久秘成人久久无码| 国内操B电影| 久久91欧美特黄A片| 麻豆AV片| 激情五月天小说网| 亚洲综合免费观看| 高清无码三级片在线观看| 嘿咻嘿咻动态图| 免费视频一区| 黑人人妻黑人ThePorn| 国产A片电影| A片地址| 久久这里| 国产不卡在线观看| 草草操| 精品人妻一区二区三区在| 五月天激情性爱| 精品人妻一区二区免费蜜桃| 十八禁网站在线| www.久久99| 理论片91| 91.xxxx| 深爱激情综合| 91视频久久| 91超碰人人操| 看一级黄色视频| 国产一级免费在线观看| www.日韩精品| 天天综合网久久综合网| 在线视频污| 欧美精品国产动漫| 欧美一级在线观看| 成人激情五月天| 国产精品久久久久久久久久久久久久久| 久久艹精品视频| 亚洲天堂视频在线观看| 色婷婷亚洲综合| 无码人妻一区二区三区免水牛视频 | 色哟哟无码精品一区二区三区| 中文无码日本高潮喷水| www深夜成人a√在线| 毛片一级片| 亚洲欧洲日韩综合| 中文字幕av网站| 婷婷五月天激情俺来也| 囯产精品久久久久久久久久| 波多野结衣一区二区三区在线观看| 国产系列精品AV| www超碰在线| 亚洲在线免费视频| www.777av| 亚洲综合在线播放| 欧美一级片免费观看| 久操伊人大香蕉| 国产高清视频在线观看| 欧美A在线| 中国特级毛片| 在线免费看A| 日韩美毛片| www国产亚洲精品久久网站| 欧美v| 国产成人影视在线观看| 国产成人久久777777| 天天日天天干麻豆| 久久国产精品波多野结衣AV| 国产一区二区视频在线观看| 亚洲九区| 操BBB操BBB| 精品免费黄色视频| 久久精彩偷拍视频| 日韩在线中文| 操天天操| 国产一片黑夜内射| 色猫咪av| 国产3p露脸普通话对白| 午夜无码鲁丝片午夜精品一区二区| 国产第一页在线观看| 国精产品一品二品国精| av婷婷五月天| 国产老女人农村HD| WW免费视频| 欧美精品成人免费片| 特级黄色毛片| 国产黄片网站| 东北老女人操逼视频| 亚洲有码中文字幕| 成年人激情网| 亚洲色图一区二区| 秋霞久久日| 小骚逼操死你| 久久久免费| 激情小说五月天| 91人妻人人爽人人澡| 嫩草国产在线| 九九中文字幕| 日韩欧美性爱| 操比视频| H片在线观看| 黄色视频| 日韩中文毛片| 久久久久久99| 理论毛片| 国产一级婬片A片AAA樱花| 人人人人人人人人操| 人人爽人人爽人人| 天天日天天操天天日| 淫荡五月天视频导航| 欧美一区二区三区四区视频| 在线中文字幕av| 成人精品国产| 亚洲图片小说区| 欧美亚洲日韩在线观看| 亚洲精品二| 韩国一级AV| 西西444WWW无码视频软件| 秋霞精品一区二区三区| 亚洲天堂视频在线观看| 中文字幕伊人| 日本不卡一区二区三区| 在线播放JUY-925被丈夫上司侵犯的第7天 | 日韩在线免费| 免费看黄色的视频| 蜜桃av色偷偷av老熟女| 人妻在线免费视频| 日韩无码一区二区三区四区| 91人人妻人人妻人人澡| 五月丁香六月久久| 亚洲二区后入极品| 日本三级在线| 99久视频| 日本a片在线观看| 国产成人精品av| 久久久成人网站| 日韩日韩日韩日韩| H网站在线观看| 国产综合久久久777777色胡同| 国产一级操逼片| 操逼操逼操| 国产精品自拍一区| 污视频在线观看免费| 黃色A片一級二級三級免費久久久 亚洲AV无码第一区二区三区蜜桃 亚洲综合免费观看高清完整版在线 | 韩日无码视频| 九九碰九九爱97超碰| 干老女人视频| 91人妻人人澡人人爽精品| 日韩中文字幕在线人成网站| 五月天福利影院| 国产日韩二区| 特级特黄AAAA免费看| 足交在线播放| 天堂中文8资源在线8| 夜夜夜操操操| 欧美色图亚洲另类| 日韩丰满人妻| 天天摸天天摸| 精品孕妇一级A片免费看| 国产成人精品视频免费看| 久久黄色免费看| 4虎亚洲人成人网www| 亚州毛多色色精品| 无码秘蜜桃一区二区| 国产AV资源| 国产一级黄色电影| 77Q视频| 操逼黄色视频| 日韩91| 国产在线小视频| 91人妻人人澡人人爽| 婷婷欧美| 九九成人| 日本无码一区二区三三| 欧美口爆| 久久亚洲视频| 在线一区| 驲韩在线视频免费观看| 蜜桃av.38| 久久电影五月天| 草久美女| 伊人成人视频在线观看| 国产毛片一照区| 欧美性极品少妇精品网站| 亚洲国产97| 国产欧美一区二区三区国产幕精品 | 91AV无码| 亚洲黄色视频在线| 91精品丝袜久久久久久久久粉嫩| 亚洲特级毛片| 亚洲无码在线免费| 国产A片免费观看| 在线观看视频黄| 黄色成人在线免费观看| 国产三级电影在线观看| 欧美午夜成人| 成人性爱AV| 亚洲精品99| 99视频网站| 欧美日韩三级| h片在线观看| 亚洲国产高清在线观看视频| 久久精品99视频| 人人操人人爽人人爱| 一级成人视频| 宅男噜| 51伦理| 国产污视频在线观看| 加勒比无码视频| www狠狠| 91亚洲综合| 亚洲第一色图| 欧美在线一级| 人妖毛片| 先锋影音av资源网| 免费的av| 国产高清自拍| 国产高清做爱免费在线视频| 精品免费囯产| 羞羞AV| 神马午夜影院| 丰满熟妇高潮呻吟无码| 国产99精品视频| 亚洲AV永久无码成人| 麻豆射区| 91网站免费看| 亚洲欧美一区二区三区在线| 国产中文字幕视频| 丁香五香天堂网| 中文字幕在线观看福利视频| 色天堂视频在线观看| 亚洲成人一| 欧洲亚洲无码| 成人精品一区二区三区无码视频| 色噜噜一区二区三区| 蜜桃毛片| av资源免费观看| 无码专区视频| 色综合色| 亚洲男人天堂| 婷婷天天干| 蜜桃人妻| 日韩一区二区三区免费视频| 中文字幕一区二区三区在线观看 | 99re视频精品| www.91九色| 波多野结衣操逼| 蝌蚪窝免费视频| 蜜芽成人网| 亚洲精品乱码久久久久久蜜桃91 | 日韩美毛片| 不卡AV在线播放| 96精品| 羽月希奶水饱胀在线播放| 男人天堂久久| 黄色成人网站在线观看免费| 久久久久久亚洲AV无码专区 | 欧美婬乱片A片AAA毛片地址| 五月天亚洲色图| 久操免费在线视频| 五月天性爱视频| 亚洲字幕在线播放| 99热思思| 成人黃色A片免费看| 亚洲中文字幕色| 翔田千里無碼破解| 国产在线观看AV| 高清无码三级片| 天天躁狠狠躁夜躁2024| 中文无码熟妇一区二区| 天天透天天干| 182在线视频| 一区二区水蜜桃| 操逼影视| 日本在线播放| 看欧美黄片| 996热re视频精品视频| 一区二区三区在线观看免费| 乱伦一级| 91做爱| 91精品婷婷国产综合久久韩漫| 国产一级特黄aaa大片| 成人性爱视频免费在线观看| 日皮网站在线观看| 深夜福利av| 午夜无码AV| 亚洲天天干| 欧美综合视频在线观看| 成人H在线| 2025AV在线| 日本高潮视频| 91人人妻| 成人免费毛片果冻日本| 躁BBB躁BBB躁BBBBBB日视频| 91麻豆精品无码人妻| a天堂8在线资源| 国产一级a爱做片免费☆观看| 亚洲天堂视频在线观看| 中文在线最新版天堂8| 吃奶做爱视频| 99国产热| 亚洲v天堂| 成人视频网| 亚洲av二区| 特级西西西88大胆无码| 亚洲无码一二区| 久久综合电影| 亚洲精品视频在线观看网站 | 国产一级片电影| 中文字幕在线观看不卡| 3D动漫啪啪精品一区二| 日本的黄色视频| jzzijzzij亚洲成熟少妇在线观看| 国产成人自拍视频在线观看| 亚洲电影中文字幕| 色婷婷久久综合久色| 豆花网无码视频观看| 在线观看日韩精品| 国产视频一区二区在线观看| 高清国产mv在线观看| 日韩无码中文字幕| 日韩免费看片| 人人天天操| 日韩精品电影| 99精品视频在线观看| 欧美一级A片免费看视频小说| 欧美黄色性爱| 一级欧美| 天天色天天色| 成人动漫免费观看| 99er在线观看视频| 东京热一区二区三区| 一区二区三区四区在线| 大香蕉综合伊人| 丝袜一区二区三区| 亚洲黄色免费在线观看| 九九99电影| 大香蕉久久精品| 日韩人妻码一区二区三区| 欧美男人天堂| 日本人妻中出| 国产在线性爱视频| 丰满人妻无码| 激情六月婷婷| 特黄A级毛片| 午夜无码三级| 特级毛片片A片AAAAAA| 欧美三级在线| 欧美精品一级| 欧美视频a| 欧美性爱一区二区| 欧美性爱高清| 91成人网站| 久久免费视频观看| 很很日| 无码专区亚洲| 亚洲自拍无码| 亚洲激情在线| 一区二区三区四区在线视频| 精品人妻一区二区三区在线视频不卡| 亚洲A视频| 国产无遮挡又黄又爽在线观看| 69成人在线电影| 无码一区二区视频| 久久天堂| 国产成人片在线观看| 欧美性夜黄A片爽爽免费视频 | 亚洲一区日韩| 欧美性爱在线播放| 99爱爱| 一级黄色AV片| 天堂网色| v在线| 韩国精品久久久| 天天日av| www.91国产| 性感成人在线| 99成人在线视频| 欧美日韩东京热| 中文字幕免费视频| 嫩BBB搡BBB搡BBB四川| 91麻豆精品国产91久久久吃药| 中文字幕成人电影| 国产精品伦子伦免费视频| 一级黄色操逼视频| 亚洲无码电影在线| 色久影院| 一本久久精品一区二区| 99爱视频| 天天看天天色| 人人澡人人澡人人| 一本色道久久综合亚洲精东小说| 成人18视频| av资源免费观看| 中文爱爱视频| 日韩三级在线播放| 午夜AV无码| 亚洲无码A片在线| 一线毛片| 大香蕉伊在线观看| 2018天天操天天干| 懂色av懂色av粉嫩av无码| 亚洲中文无码在线| re久久| 国产三级在线观看视频| 夜夜骚精品人妻av一区| 91无码国产成人精品| 男人天堂2024| 久久激情国产| 国产动态图|