欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

深入淺出主流的幾款小程序跨端框架原理 - 新聞資訊 - 云南小程序開(kāi)發(fā)|云南軟件開(kāi)發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開(kāi)發(fā)/軟件開(kāi)發(fā)

知識(shí)

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們?cè)谧非笃湟曈X(jué)表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營(yíng)銷(xiāo)的便利,運(yùn)營(yíng)的高效,讓網(wǎng)站成為營(yíng)銷(xiāo)工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏?jí)提供便捷的支持!

您當(dāng)前位置>首頁(yè) » 新聞資訊 » 小程序相關(guān) >

深入淺出主流的幾款小程序跨端框架原理

發(fā)表時(shí)間:2021-1-5

發(fā)布人:葵宇科技

瀏覽次數(shù):77

目前,小程序在用戶(hù)規(guī)模及商業(yè)化方面都取得了極大的成功。微信、支付寶、百度、字節(jié)跳動(dòng)等平臺(tái)的小程序日活都超過(guò)了3億。

我們?cè)陂_(kāi)發(fā)小程序時(shí)仍然存在諸多痛點(diǎn):小程序孱弱簡(jiǎn)陋的原生開(kāi)發(fā)體驗(yàn),注定會(huì)出現(xiàn)小程序增強(qiáng)型框架,來(lái)提升開(kāi)發(fā)者開(kāi)發(fā)體驗(yàn);各家廠(chǎng)商小程序API碎片化的現(xiàn)狀,注定會(huì)有多端框架會(huì)成為標(biāo)配,由跨端框架肩負(fù)跨平臺(tái)移植挑戰(zhàn)。

正是因?yàn)殚_(kāi)發(fā)者對(duì)于提升小程序開(kāi)發(fā)效率有著強(qiáng)烈需求,小跨端框架發(fā)展到如今已經(jīng)百花齊放、百家爭(zhēng)鳴:除了美團(tuán)的 mpvue 、網(wǎng)易的 megalo 、滴滴的 chameloen 已經(jīng)趨于穩(wěn)定,京東的 Taro開(kāi)始探索 taro next, Hbuilder 的uni-app 產(chǎn)品和生態(tài)持續(xù)完善,微信新推出了支持H5和微信小程序的 kbone 框架,螞蟻金服的 remax

上述的這么多跨端框架紛繁復(fù)雜,我們可以從下面兩個(gè)維度進(jìn)行分類(lèi):

小程序跨端框架的分類(lèi)

按語(yǔ)法分類(lèi)

從框架的語(yǔ)法來(lái)說(shuō),可以分為下面兩類(lèi):

  • Vue 語(yǔ)法
  • React 語(yǔ)法 / 類(lèi) React 語(yǔ)法

主流的跨端框架基本遵循 React、Vue 語(yǔ)法,這也比較好理解,可以復(fù)用現(xiàn)有的技術(shù)棧,降低學(xué)習(xí)成本。










remaxTaro nextTaro 1/2megalompvueuni-appchameloen
語(yǔ)法reactreact類(lèi) react (nerve)vuevuevue類(lèi) vue
廠(chǎng)家螞蟻金服京東京東網(wǎng)易考拉美團(tuán)Hbuilder滴滴

按實(shí)現(xiàn)原理分類(lèi)

從實(shí)現(xiàn)原理上,開(kāi)源社區(qū)的跨端框架大致分為下面兩類(lèi):

  • compile time 編譯時(shí)
  • runtime 運(yùn)行時(shí)

compile time 編譯時(shí)的跨端框架,主要的工作量在編譯階段。他們框架約定了一套自己的 DSL ,在編譯打包的過(guò)程中,利用 babel 工具通過(guò) AST 進(jìn)行轉(zhuǎn)譯,生成符合小程序規(guī)則的代碼。

這種方式容易出現(xiàn) BUG ,而且開(kāi)發(fā)限制過(guò)多。早期的 Taro 1.0 和 2.0 的版本就是采用的這種方案,下文會(huì)有更具體的介紹。

而另外一種runtime 運(yùn)行時(shí)模式, 跨端框架真正的在小程序的邏輯層中運(yùn)行起來(lái) React 或者是 Vue 的運(yùn)行時(shí),然后通過(guò)適配層,實(shí)現(xiàn)自定義渲染器。這種方式比靜態(tài)編譯有天然的優(yōu)勢(shì),所以 Taro 的最新 Next 版本和 Remax 采用的是這種方案。

寫(xiě)在小程序跨端原理之前

通過(guò)上文我們知道小程序跨端框架目前有很多嘛,各個(gè)大廠(chǎng)都會(huì)有自己的一套,百花齊放。文章篇幅有限,如果要分別拆開(kāi)講清楚他們各家實(shí)現(xiàn)的細(xì)節(jié),是一件很困難同時(shí)很費(fèi)時(shí)間的事情。

所以,下文會(huì)嘗試梳理一下主流小程序一些共用性的通用實(shí)現(xiàn)原理, 盡量會(huì)屏蔽忽略掉各家實(shí)現(xiàn)一些細(xì)枝末節(jié)的細(xì)節(jié)差異,也不會(huì)在文章中貼大段的源碼分析,而是通過(guò)偽代碼來(lái)代替。

下面,我們會(huì)從 Vue 跨端框架React 跨端框架兩個(gè)大方向,進(jìn)入到小程序跨端原理的世界,講解這些跨端框架的核心原理,深入到源碼底層去分析,揭開(kāi)他們神秘的面紗。

Vue 跨端框架

當(dāng)你使用 megalompvue 這些 Vue 跨端框架時(shí),看上去,我們寫(xiě)的是vue 的代碼,然后打包編譯之后就可以運(yùn)行在小程序內(nèi),是不是很神奇?這些框架背后做了哪些事情呢?

實(shí)際上,這些 Vue的跨端框架 核心原理都差不多,都是把 Vue 框架拿過(guò)來(lái)強(qiáng)行的改了一波,借助了 vue 的能力。比如說(shuō),vue 的編譯打包流程(也就是vue-loader的能力), vue 的響應(yīng)式雙向綁定、虛擬dom、diff 算法。上面這些東西跨端框架都沒(méi)有修改,直接哪來(lái)用的。

那么哪些部分是這些跨端框架自己新加的東西呢?

涉及到 Vue 框架中操作DOM節(jié)點(diǎn)的代碼。

這些跨端框架,把原本Vue框架中原生 javascript 操作 DOM 的方法,替換成小程序平臺(tái)的 setData()。為什么要這樣呢?不著急,下文會(huì)有比較詳細(xì)的講解。

不著急,慢慢來(lái),我們先從一個(gè)最簡(jiǎn)單的問(wèn)題開(kāi)始。

vue 到 小程序

首先我們來(lái)看,一個(gè) vue 的單文件,究竟做了啥,怎么就能跑在小程序里面了?

我們知道,對(duì)于微信小程序來(lái)說(shuō),需要有 4份文件:.wxml、.wxss、.js、 .json。

(上面是去微信小程序官網(wǎng)截的圖)

而對(duì)于一個(gè) Vue 組件來(lái)說(shuō),一個(gè) vue 文件有三個(gè)部分組成:template, script, style。

那么,這些跨端框架把Vue 單文件中的 <template>、 <script>、<style>這三個(gè)部分對(duì)應(yīng)的代碼,拆一拆,分別處理編譯一下,分到 .wxml.wxss、.js、 .json 這 4 份文件中,如下圖所示:

我們分別從<template>、 <script>、<style>這三個(gè)部分來(lái)討論:

  • <style> 部分是最簡(jiǎn)單的。一般來(lái)說(shuō),在 h5 環(huán)境中的 css 樣式,大部分都可以直接挪到 .wxss,需要處理的部分比較少,除了少部分不支持的屬性和 小程序的單位轉(zhuǎn)換
  • <template> 轉(zhuǎn)換到 .wxml稍微復(fù)雜一點(diǎn)。我們需要把 h5 的標(biāo)簽啊、vue特殊的語(yǔ)法替換成小程序的標(biāo)簽、小程序特殊的語(yǔ)法。替換的工作我們稱(chēng)為 模板替換 ,下文會(huì)有一個(gè)章節(jié)用來(lái)介紹。
  • 最難的是<script>.js, 涉及到 vue 的運(yùn)行時(shí) 如何和 小程序的實(shí)例通訊的問(wèn)題,這一部分會(huì)用比較多的章節(jié)去介紹。

接下來(lái),我們先看模板替換 ,也就是template 生成 .wxml 文件的過(guò)程。

<template>.wxml

Vue 是采用 template 語(yǔ)法的,各大廠(chǎng)商的小程序也是采用了 template 語(yǔ)法。從 Vue 的 template 轉(zhuǎn)變成小程序的 template 相對(duì)比較簡(jiǎn)單,React 的 jsx 轉(zhuǎn)變?yōu)樾〕绦虻?template 就相對(duì)比較棘手啦。

Vue 的 template 與小程序的 template 大體是上的語(yǔ)法很類(lèi)似,但是還是有不一樣的地方。例如小程序里沒(méi)有 <div> 標(biāo)簽,而是小程序廠(chǎng)商提供的 <view> 標(biāo)簽等等

因此我們需要把 Vue 模版轉(zhuǎn)換為微信小程序的 .wxml。

例如上圖所示,<div> 標(biāo)簽需要轉(zhuǎn)換成 <view> 標(biāo)簽,一些 vue 中的語(yǔ)法也需要進(jìn)行轉(zhuǎn)化成對(duì)應(yīng)小程序平臺(tái)的語(yǔ)法。

再比如說(shuō),在 Vue 里面綁定事件常用 @methodName 的語(yǔ)法, 轉(zhuǎn)成小程序模版則需要用 bind,同時(shí)用 tap 事件替換 click 事件。

除了這個(gè),還有一些vue的模板語(yǔ)法,也需要轉(zhuǎn)成小程序的模板語(yǔ)法

Vue 和小程序插值表達(dá)式則是一樣的,采用了雙花括號(hào),可以不需要做任何轉(zhuǎn)化

上面展示的這些模板替換,都只是替換為微信小程序的語(yǔ)法。轉(zhuǎn)化為其他小程序平臺(tái)的語(yǔ)法也是類(lèi)似的思路,如下圖所示:

那么,模板的轉(zhuǎn)化具體是如何實(shí)現(xiàn)的呢? 我們的第一想法是通過(guò)正則來(lái)匹配,但是要寫(xiě)出匹配出所有情況的正則是非常困難的。

實(shí)際上,mpvue、megalo、uni-app 的框架是采用了 ast 來(lái)解析轉(zhuǎn)化模板的。

模板替換過(guò)程其實(shí)就是兩側(cè)對(duì)齊語(yǔ)法的過(guò)程,把語(yǔ)法不一致的地方改成一樣的,是一個(gè) case by case 的過(guò)程,只要匹配到不同情況下語(yǔ)法即可,比較費(fèi)功夫但是難度系數(shù)不是很高。

接下來(lái)我們看如何把 <script> 中的內(nèi)容,挪到小程序 .js 中呢?

<script>.js

我們?cè)?.vue 單文件中的 script 部分中, 通常會(huì)寫(xiě)下面的代碼,我們會(huì)寫(xiě)一個(gè) Vue 的配置項(xiàng)對(duì)象傳入到 Vue 構(gòu)造函數(shù)中,然后 new Vue() 會(huì)實(shí)例化出來(lái)一個(gè) vue 實(shí)例。

new Vue({
  data(){},
  methods: {},
  components: {}  
})
復(fù)制代碼

上面的代碼是完全可以跑在小程序的邏輯層里面的,只要引入vue 即可,畢竟 Vue 大部分就是純粹的 javascript。也就是說(shuō),小程序的渲染層里面是完全可以直接運(yùn)行起來(lái) Vue 的運(yùn)行時(shí)和 React 的運(yùn)行時(shí)的。

但是這樣還不夠,小程序平臺(tái)還規(guī)定,要在小程序頁(yè)面中調(diào)用 Page() 方法生成一個(gè) page 實(shí)例, Page() 方法是小程序官方提供的 API。

在一個(gè)小程序的頁(yè)面中,是必須有 Page() 方法的。微信小程序會(huì)在進(jìn)入一個(gè)頁(yè)面時(shí),掃描該頁(yè)面中的 .js 文件,如果沒(méi)有調(diào)用 Page() 這個(gè)方法,頁(yè)面會(huì)報(bào)錯(cuò)。

如下圖所示,我們?cè)?<script> 中寫(xiě)的是 new Vue() 這樣子的代碼,而微信想要的是 Page()

那么,應(yīng)該怎么解決呢?

Vue 跨端框架他們拓展了 Vue 的框架,把 Vue2.0 的源碼直接拷貝過(guò)來(lái),改了里面的初始化方法,在初始化方法中調(diào)用了 Page() 方法, 如下面?zhèn)未a所示:

new Vue() {};
Vue.init = () => { 
  // 在 vue 初始化的時(shí)候,調(diào)用了 page() 方法
  Page()
}   
復(fù)制代碼

在 vue 實(shí)例化的時(shí)候,會(huì)調(diào)用 init 方法,在 init 方法里面會(huì)調(diào)用 Page() 函數(shù),生成一個(gè)小程序的 page 實(shí)例。

這樣,我們?cè)谝粋€(gè)小程序頁(yè)面中,就會(huì)同時(shí)存在一個(gè) vue 的實(shí)例,和一個(gè)小程序的 page 實(shí)例,他們是如何融合起來(lái)一起工作的呢?他們之間是如何做到數(shù)據(jù)管理的? 如何進(jìn)行通訊的呢?

接下來(lái)就涉及到 Vue 框架的核心流程了,為了方便一些不了解 Vue 同學(xué),同時(shí)也為了更好的深入理解下面講的內(nèi)容,接下來(lái)會(huì)稍微講一丟丟 vue 的核心流程。

  • ( 真的只有一丟丟 )

Vue 的核心流程

如下圖左側(cè)所示,簡(jiǎn)單來(lái)說(shuō), 一個(gè) .vue 的單文件由三部分構(gòu)成: template, script, style

我們先看上圖中的橙黃色的路徑,也就是 template 部分的處理過(guò)程。

如下圖所示,template 模板部分會(huì)在編譯打包的過(guò)程中,被 vue-loader 調(diào)用 compile 方法通過(guò)詞法分析生成一個(gè) ast 對(duì)象,然后調(diào)用代碼生成器,經(jīng)過(guò)遍歷 AST 樹(shù)遞歸的拼接字符串操作,最終生成一段 render 函數(shù), render函數(shù)最后會(huì)存在打包生成的dist 文件中。

可以看下面這個(gè)例子,一段簡(jiǎn)單的 template 模板如下所示:

<div class="ctl-view" @click="handleClick">
  {{ a }}
</div>
復(fù)制代碼

經(jīng)過(guò)編譯之后,通過(guò) ast 進(jìn)行分析,生成的 render 函數(shù)如下:

_c("div", 
    { staticClass: "ctl-view", on: { click: _vm.handleClick } },
    [_vm._t("default")]
)
復(fù)制代碼

render 函數(shù)會(huì)在第一次 mount時(shí),或者Vue 維護(hù)的 data 有更新產(chǎn)生的時(shí)候會(huì)被執(zhí)行。

那么執(zhí)行下面這段 render 函數(shù)會(huì)拿到什么呢?

上面圖中藍(lán)色圓圈中的 _c 方法是創(chuàng)建元素類(lèi)型的vnode, 而 _v 方法是創(chuàng)建 文本類(lèi)型的vnode。

Render 函數(shù)中會(huì)調(diào)用這些方法創(chuàng)建不同類(lèi)型的vnode,最終的產(chǎn)物是生成好的虛擬DOM樹(shù) vnode tree,對(duì)應(yīng)上面圖中 render 函數(shù)的下一個(gè)階段 vnode。

虛擬DOM樹(shù)是對(duì)真實(shí)DOM樹(shù)的抽象,樹(shù)中的節(jié)點(diǎn)被稱(chēng)作 vnode 。 vnode 有一個(gè)特點(diǎn), 它保存了這個(gè)DOM節(jié)點(diǎn)用到了哪些數(shù)據(jù) ,這一點(diǎn)非常重要。

Vue拿到 虛擬dom樹(shù)之后,就可以去和上次老的虛擬dom樹(shù)patch diff 對(duì)比。

這一步的目的是找出,我們應(yīng)該怎么樣改動(dòng)現(xiàn)存的老的DOM樹(shù),代價(jià)才最小。

patch 階段之后,如果是運(yùn)行在瀏覽器環(huán)境中, vue 實(shí)例就會(huì)使用真實(shí)的原生 javascript 操作DOM的方法(比如說(shuō) insertBefore , appendChild 之類(lèi)的),去操作DOM節(jié)點(diǎn),更新瀏覽器頁(yè)面的視圖。

接下來(lái),我們?cè)賮?lái)看一下上面圖中,藍(lán)色的線(xiàn)條的路徑。

在new Vue 的時(shí)候,Vue 在初始化的時(shí)候會(huì)對(duì)數(shù)據(jù) data 做響應(yīng)式的處理,當(dāng)有數(shù)據(jù)發(fā)生更新時(shí),最后會(huì)調(diào)用上文的 render 函數(shù),生成最新的虛擬DOM樹(shù)。

接著對(duì)比老的虛擬DOM 樹(shù)進(jìn)行 patch, 找出最小修改代價(jià)的vnode 節(jié)點(diǎn)進(jìn)行修改。

上面介紹的流程就是 vue 的整體流程啦。

(如果有不理解的地方,不重要,也不需要擔(dān)心會(huì)阻塞下文的閱讀)

我們要關(guān)心的是,下面的類(lèi) vue 小程序跨端框架的核心流程。接下來(lái)一起來(lái)看吧。

類(lèi) vue 小程序跨端框架的核心流程

在進(jìn)一步講解之前,我們先思考一個(gè)問(wèn)題。上圖中,Vue 在 diff 之后就是操作了原生的 DOM 元素,但是各家廠(chǎng)商的小程序不支持原生DOM操作,因此也就沒(méi)有修改視圖節(jié)點(diǎn)的能力。那么我們?cè)趺礃硬拍芨滦〕绦虻囊晥D呢?

下面這張圖代表了類(lèi) vue 小程序跨端框架的核心流程圖。

咋一看這張圖,會(huì)發(fā)現(xiàn)和上面Vue的圖是很像的。畢竟 megalo 、 mpvue 等小程序框架,本質(zhì)都是對(duì) vue 的拓展(copy過(guò)來(lái)改了改)

仔細(xì)和上面的 vue 的核心流程圖一對(duì)比,我們發(fā)現(xiàn),小程序跨端框架的流程圖替換掉 vue 原本的 DOM 操作,替換為新增的綠色的setData 操作, 同時(shí)還多了一個(gè)綠色框框中的的 Page() 方法。

Page() 方法上文有介紹過(guò)原因

setData() 是小程序官方提供的 API,用來(lái)修改小程序 page 實(shí)例上的數(shù)據(jù),從而會(huì)更新小程序的視圖。

『替換掉 vue 原本的 DOM 操作』這一個(gè)點(diǎn)比較容易理解,因?yàn)樾〕绦蛉萜鞑](méi)有提供操作小程序節(jié)點(diǎn)的 API 方法,這是因?yàn)樾〕绦蚋綦x了渲染進(jìn)程 (渲染層)和邏輯進(jìn)程 (邏輯層),如下圖所示:

在小程序容器中,邏輯層到渲染層的更新,只能通過(guò) setData() 來(lái)實(shí)現(xiàn)。

不管是 mpvue、megalo ,還是uniapp,這些類(lèi) vue 跨端框架,都是通過(guò)這種方法來(lái)更新視圖的。而且,在未來(lái)可預(yù)見(jiàn)的幾年里,只要小程序廠(chǎng)商不提供修改小程序節(jié)點(diǎn)的 API 方法,小程序跨端框架更新 DOM 節(jié)點(diǎn)仍然會(huì)通過(guò) setData 這種 API

好了,到了這一步,我們已經(jīng)知道了,跨端框架替換了 Vue 框架中 JS 操作DOM 原生節(jié)點(diǎn)的 API setData() 來(lái)更新小程序的頁(yè)面。

但是我們還是不知道具體背后做了什么,接下來(lái),看一個(gè)具體的例子:

new Vue({
  data(){
    return {
      showToggle: true
    }
  }
})


// 下面是經(jīng)過(guò) 模板替換 之后的代碼
<view wx:if="{{showToggle}}">
</view>
復(fù)制代碼

在上面的例子中,showToggle 這個(gè)變量代表的數(shù)據(jù)是維護(hù)在Vue 實(shí)例上的。

在頁(yè)面初始化的時(shí)候,我們的小程序跨端框架就開(kāi)始執(zhí)行了,它會(huì)先實(shí)例化一個(gè)Vue 實(shí)例,然后調(diào)用小程序官方的 Page() API 生成了小程序的page 實(shí)例,并在在 Vue 的 mounted 中會(huì)把數(shù)據(jù)同步到小程序的 page 實(shí)例上。

因此在實(shí)際頁(yè)面打開(kāi)之后,會(huì)同時(shí)存在小程序原生的Page 實(shí)例和 Vue 實(shí)例。vue 實(shí)例上有數(shù)據(jù)(我們的 data 本來(lái)就是定義在 vue 里面的),小程序Page 實(shí)例上也有數(shù)據(jù)(小程序?qū)嵗蠜](méi)數(shù)據(jù)沒(méi)法渲染頁(yè)面對(duì)吧)。

當(dāng) Vue 中的數(shù)據(jù)發(fā)生變化時(shí),會(huì)觸發(fā) Vue 響應(yīng)式的邏輯,走 上圖中Vue 更新的那一套邏輯:重新執(zhí)行 render 函數(shù)