知識(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í)成本。
remax | Taro next | Taro 1/2 | megalo | mpvue | uni-app | chameloen | |
語(yǔ)法 | react | react | 類(lèi) react (nerve) | vue | vue | vue | 類(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)你使用 megalo
、mpvue
這些 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
的框架,把 Vue
2.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ù)
相關(guān)案例查看更多
相關(guān)閱讀
- 網(wǎng)站排名優(yōu)化
- 云南花農(nóng)小程序
- 云南小程序開(kāi)發(fā)制作公司
- 商標(biāo)注冊(cè)
- 云南網(wǎng)站建設(shè)特性
- 百度排名
- typescript
- 云南網(wǎng)站制作哪家好
- 網(wǎng)站建設(shè)方法
- 昆明做網(wǎng)站建設(shè)的公司排名
- 重慶網(wǎng)站建設(shè)公司
- 小程序公司
- 昆明小程序定制開(kāi)發(fā)
- .net網(wǎng)站
- 小程序開(kāi)發(fā)費(fèi)用
- 云南微信小程序開(kāi)發(fā)
- 小程序被騙退款成功
- web開(kāi)發(fā)
- 云南軟件設(shè)計(jì)
- 曲靖小程序開(kāi)發(fā)
- 昆明小程序開(kāi)發(fā)
- 商標(biāo)
- 汽車(chē)報(bào)廢回收管理系統(tǒng)
- 云南網(wǎng)站建設(shè)方案 doc
- 網(wǎng)站建設(shè)列表網(wǎng)
- 云南網(wǎng)站建設(shè)哪家好
- 汽車(chē)回收管理系統(tǒng)
- 云南etc小程序
- 網(wǎng)站建設(shè)首選公司
- 百度小程序開(kāi)發(fā)