隨著小程序的發(fā)展與功能的逐步完善,越來越多的產品需要小程序與 APP 的功能能有一些共性,社區(qū)跨平臺的解決方案越來越多,比如 taro 等為代表的把一套代碼編譯成多端運行的機制,本文會使用 Swift 作為原生語言,在 iOS 應用上運行一個小程序 Demo, 使用 Android && React Native 也可以采用同樣的思路實現(xiàn)。 相關代碼倉庫: https://github.com/taixw2/rmini 編譯層編譯的目的是為了抹平小程序的與 H5 的差異,利用 Vue 實現(xiàn)數據綁定,利用 Web Component 實現(xiàn)小程序的組件功能。 從官網文檔中可以看出來,運行一個小程序需要框架(數據綁定渲染)、組件(小程序渲染單元)、api(與原始交互的能力)。 框架實現(xiàn)轉換成單頁應用(一種可行的方案)把所有頁面打包成一個 js, 再由 js 管理所有的路由和狀態(tài),這種方案適合在 web 端運行,并且是單引擎的方案,在模擬原生的右滑返回等效果也會不盡人意。 轉換成多頁面眾所周知,小程序是一個雙引擎的框架,上面的方案顯然不能達到要求, 雙引擎的特點是在運行 javascript 的黑盒子中,無法訪問到 DOM && BOM 等。將所有的邏輯代碼在原生的 JavascriptCore 中運行,WebView 中的 Javascript 引擎負責數據綁定,需要解決的難點是 JavascriptCore 中的 setData 怎么通知 WebView 渲染, WebView 的事件怎么執(zhí)行 JavascriptCore,接著往下看。 抹平WXMLwxml 是一種類 html 標記語言,他負責所有的渲染規(guī)則,包括條件渲染、列表渲染、數據綁定等,與其再實現(xiàn)一種框架,還不如直接利用 Vue 實現(xiàn)同樣的功能,再利用各種轉換庫將 wxml 中的事件轉換成 Vue 能夠識別的事件,如利用 每一個事件綁定的方法全都在原生的 JSContext 中運行,所以此時的事件只需要傳遞給 JSContext 的作用。 抹平WXSSwxss 作為小程序的樣式語言,其余 css 的主要區(qū)別就是多了一個 rpx 單位,以下是官網的換算表: 還有一個 抹平組件組件具有獨特的功能和自己的渲染規(guī)則,比如 這里用了 lit-element 這個框架,能夠簡化一些操作。 抹平 Page 和 AppApp 負責整個應用的生命周期以及存一些全局的數據,
初始化一個頁面都需要是實例化 PageClass, 即使再次進入(不是返回到這個頁面)這個頁面頁需要再次重新實例化,每次實例化都需要關聯(lián)一個 webviewId, 這個 ID 與原始的 webview 關聯(lián),這樣每個 PageClass 中的 setData 都能找到對應的 webview 進行再次渲染,所以對應的代碼可能是這樣的: 抹平 API通過 API 能夠直接調用原生的功能,比如 實現(xiàn)JSContext 調用原生代碼的功能,需要給 JSContext 中植入一個 JSBridge,如: 打包 JavascriptJavascript 代碼打包后被放在 JavascriptCore 中運行,唯一與 Webview 中的 JSContext 打交道的只有
打包流程及其簡單,接下來看一下兩個 Javascript 引擎的交互過程。 打通 JSContext 到 WebView JavascriptCore每次進入一個頁面的時候都需要為這個頁面的 webview 分配一個 id, 這個 id 至關重要,作為 native 與 JSContext (原生運行 javascript 的上下文對象) 與 webview 交互的唯一標識,JSContext 中需要實例化一個新的 PageClass 關聯(lián)這個 id, native 中通過 id 保留 webview 的引用。在 JSContext 中植入一個 JSBridge 用于與原生交互,如: 打通 Webview JavascriptCore 到 JSContext有了前面的鋪墊,接下來再看 webview 如何調用 JSContext 的方法, Webview 唯一能與 JSContext 交互的方式只有事件,事件觸發(fā)后,需要通過某種方式觸發(fā) JSContext 中的方法,最后調用 setData 再返回來重新渲染 webview。 webview 中綁定的方法名眾多,如: 結尾利用原生作為橋梁,在兩個引擎之間通信,webview 中的 JSContext 負責接收渲染通知,以及發(fā)送事件到 Native 的 JSContext 中,JSContext 獨立運行,所以既訪問不到 |
|