小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

探索小程序?qū)崿F(xiàn)

 小仙女本仙人 2020-08-16

隨著小程序的發(fā)展與功能的逐步完善,越來越多的產(chǎn)品需要小程序與 APP 的功能能有一些共性,社區(qū)跨平臺(tái)的解決方案越來越多,比如 taro 等為代表的把一套代碼編譯成多端運(yùn)行的機(jī)制,本文會(huì)使用 Swift 作為原生語言,在 iOS 應(yīng)用上運(yùn)行一個(gè)小程序 Demo, 使用 Android && React Native 也可以采用同樣的思路實(shí)現(xiàn)。

相關(guān)代碼倉(cāng)庫(kù): https://github.com/taixw2/rmini

編譯層

編譯的目的是為了抹平小程序的與 H5 的差異,利用 Vue 實(shí)現(xiàn)數(shù)據(jù)綁定,利用 Web Component 實(shí)現(xiàn)小程序的組件功能。

從官網(wǎng)文檔中可以看出來,運(yùn)行一個(gè)小程序需要框架(數(shù)據(jù)綁定渲染)、組件(小程序渲染單元)、api(與原始交互的能力)。

20191230232018.png

框架實(shí)現(xiàn)

轉(zhuǎn)換成單頁應(yīng)用(一種可行的方案)

把所有頁面打包成一個(gè) js, 再由 js 管理所有的路由和狀態(tài),這種方案適合在 web 端運(yùn)行,并且是單引擎的方案,在模擬原生的右滑返回等效果也會(huì)不盡人意。

20191230234134.png

轉(zhuǎn)換成多頁面

眾所周知,小程序是一個(gè)雙引擎的框架,上面的方案顯然不能達(dá)到要求, 雙引擎的特點(diǎn)是在運(yùn)行 javascript 的黑盒子中,無法訪問到 DOM && BOM 等。將所有的邏輯代碼在原生的 JavascriptCore 中運(yùn)行,WebView 中的 Javascript 引擎負(fù)責(zé)數(shù)據(jù)綁定,需要解決的難點(diǎn)是 JavascriptCore 中的 setData 怎么通知 WebView 渲染, WebView 的事件怎么執(zhí)行 JavascriptCore,接著往下看。

20191230235833.png

抹平WXML

wxml 是一種類 html 標(biāo)記語言,他負(fù)責(zé)所有的渲染規(guī)則,包括條件渲染、列表渲染、數(shù)據(jù)綁定等,與其再實(shí)現(xiàn)一種框架,還不如直接利用 Vue 實(shí)現(xiàn)同樣的功能,再利用各種轉(zhuǎn)換庫(kù)將 wxml 中的事件轉(zhuǎn)換成 Vue 能夠識(shí)別的事件,如利用 post-html 可以做到如下的轉(zhuǎn)換:

20200101115533.png

每一個(gè)事件綁定的方法全都在原生的 JSContext 中運(yùn)行,所以此時(shí)的事件只需要傳遞給 JSContext 的作用。

抹平WXSS

wxss 作為小程序的樣式語言,其余 css 的主要區(qū)別就是多了一個(gè) rpx 單位,以下是官網(wǎng)的換算表:
20200101120721.png
根據(jù)上表可得知, rpx = (750 / 屏幕寬度) * px;
在傳統(tǒng)的移動(dòng)端頁面,我們的高清方案,一般需要獲取 dpr, 然后修改動(dòng)態(tài)修改 viewport 和 html 上的 font-size,但是小程序的代碼因?yàn)槭欠旁诹嗽O(shè)備本地,所以可以在下載小程序頁面之后,我們還有一次編譯機(jī)會(huì),這時(shí)就可以把 rpx 根據(jù)當(dāng)前設(shè)備的屏幕寬度替換成對(duì)應(yīng)的 px。

還有一個(gè) @import,則利用 scss 或 less 就可以合并到同一個(gè) css 文件中,
而全局樣式則可以在構(gòu)建 WXML 的時(shí)候再植入進(jìn)入

抹平組件

組件具有獨(dú)特的功能和自己的渲染規(guī)則,比如 scroll-view 具有 scroll-xscroll-y 等屬性控制滾動(dòng)條。在 HTML5 中有一個(gè)重大的功能web-component,它能夠自定義 html 元素,并且能夠監(jiān)控屬性的變化,非常適合實(shí)現(xiàn)小程序組件。如:(使用了 lit-element 框架)

Untitled (1).jpeg

這里用了 lit-element 這個(gè)框架,能夠簡(jiǎn)化一些操作。

抹平 Page 和 App

App 負(fù)責(zé)整個(gè)應(yīng)用的生命周期以及存一些全局的數(shù)據(jù),getApp 能獲取到 app 的信息。 所以類似的結(jié)構(gòu)可能是這樣的:

Untitled (4).jpeg

getApp 能夠直接訪問到內(nèi)部對(duì)象,并且在最頂層聲明,這樣每一個(gè)的地方都能訪問到 getApp。

初始化一個(gè)頁面都需要是實(shí)例化 PageClass, 即使再次進(jìn)入(不是返回到這個(gè)頁面)這個(gè)頁面頁需要再次重新實(shí)例化,每次實(shí)例化都需要關(guān)聯(lián)一個(gè) webviewId, 這個(gè) ID 與原始的 webview 關(guān)聯(lián),這樣每個(gè) PageClass 中的 setData 都能找到對(duì)應(yīng)的 webview 進(jìn)行再次渲染,所以對(duì)應(yīng)的代碼可能是這樣的:

Untitled (5).jpeg

抹平 API

通過 API 能夠直接調(diào)用原生的功能,比如 wx.request, 如果直接在 webview 中的 JSContext 中運(yùn)行的話,則可能存在跨域,但是放在原生就不會(huì)存在這個(gè)問題。

實(shí)現(xiàn)JSContext 調(diào)用原生代碼的功能,需要給 JSContext 中植入一個(gè) JSBridge,如: JSBridge.invokeJSBridge.on, invoke 負(fù)責(zé)同步任務(wù),on 負(fù)責(zé)異步任務(wù),原生再利用反射(原生的反射真麻煩)調(diào)用對(duì)應(yīng)的原生方法,原生可以利用 while(true) 掛起 JSContext,既可以達(dá)到同步和異步的方法。

Untitled (3).jpeg

打包 Javascript

Javascript 代碼打包后被放在 JavascriptCore 中運(yùn)行,唯一與 Webview 中的 JSContext 打交道的只有 setData, 先看一下打包流程:

  1. 利用 App.json 構(gòu)建入口文件
  2. 利用 rollup 等工具將所有 Javascript 打包成一個(gè)文件(目前沒有分包)

打包流程及其簡(jiǎn)單,接下來看一下兩個(gè) Javascript 引擎的交互過程。

打通 JSContext 到 WebView JavascriptCore

每次進(jìn)入一個(gè)頁面的時(shí)候都需要為這個(gè)頁面的 webview 分配一個(gè) id, 這個(gè) id 至關(guān)重要,作為 native 與 JSContext (原生運(yùn)行 javascript 的上下文對(duì)象) 與 webview 交互的唯一標(biāo)識(shí),JSContext 中需要實(shí)例化一個(gè)新的 PageClass 關(guān)聯(lián)這個(gè) id, native 中通過 id 保留 webview 的引用。在 JSContext 中植入一個(gè) JSBridge 用于與原生交互,如: JSBridge.setData(webviewId, appId, data), 當(dāng) JSBridge 的 setData 被調(diào)用后,通過 appId + webviewId 就能找到對(duì)應(yīng)的 webview, 再將 setData 傳入 webview 中,在 Vue 接收到 data 后進(jìn)行渲染, 整個(gè)過程如圖:

20200103232240.png

打通 Webview JavascriptCore 到 JSContext

有了前面的鋪墊,接下來再看 webview 如何調(diào)用 JSContext 的方法, Webview 唯一能與 JSContext 交互的方式只有事件,事件觸發(fā)后,需要通過某種方式觸發(fā) JSContext 中的方法,最后調(diào)用 setData 再返回來重新渲染 webview。

webview 中綁定的方法名眾多,如:bindtap="a", bindtap="b", bindtap="c" 等,但是可以通過 “抹平 WXML” 的時(shí)候最終只保留一個(gè)出口,如:
v-on:click="callClick('a', $event)" 等,這樣 vue 中的 method 只需要實(shí)現(xiàn)對(duì)應(yīng)的幾個(gè)事件便可:

Untitled (2).jpeg

結(jié)尾

利用原生作為橋梁,在兩個(gè)引擎之間通信,webview 中的 JSContext 負(fù)責(zé)接收渲染通知,以及發(fā)送事件到 Native 的 JSContext 中,JSContext 獨(dú)立運(yùn)行,所以既訪問不到 window 對(duì)象,也訪問不到 document 對(duì)象。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多