探索小程式實現

来源:https://www.cnblogs.com/Amy-so/archive/2020/01/05/12152225.html
-Advertisement-
Play Games

隨著小程式的發展與功能的逐步完善,越來越多的產品需要小程式與 APP 的功能能有一些共性,社區跨平臺的解決方案越來越多,比如 taro 等為代表的把一套代碼編譯成多端運行的機制,本文會使用 Swift 作為原生語言,在 iOS 應用上運行一個小程式 Demo, 使用 Android && React ...


隨著小程式的發展與功能的逐步完善,越來越多的產品需要小程式與 APP 的功能能有一些共性,社區跨平臺的解決方案越來越多,比如 taro 等為代表的把一套代碼編譯成多端運行的機制,本文會使用 Swift 作為原生語言,在 iOS 應用上運行一個小程式 Demo, 使用 Android && React Native 也可以採用同樣的思路實現。

相關代碼倉庫: https://github.com/taixw2/rmini

編譯層

編譯的目的是為了抹平小程式的與 H5 的差異,利用 Vue 實現數據綁定,利用 Web Component 實現小程式的組件功能。

從官網文檔中可以看出來,運行一個小程式需要框架(數據綁定渲染)、組件(小程式渲染單元)、api(與原始交互的能力)。

20191230232018.png

框架實現

轉換成單頁應用(一種可行的方案)

把所有頁面打包成一個 js, 再由 js 管理所有的路由和狀態,這種方案適合在 web 端運行,並且是單引擎的方案,在模擬原生的右滑返回等效果也會不盡人意。

20191230234134.png

轉換成多頁面

眾所周知,小程式是一個雙引擎的框架,上面的方案顯然不能達到要求, 雙引擎的特點是在運行 javascript 的黑盒子中,無法訪問到 DOM && BOM 等。將所有的邏輯代碼在原生的 JavascriptCore 中運行,WebView 中的 Javascript 引擎負責數據綁定,需要解決的難點是 JavascriptCore 中的 setData 怎麼通知 WebView 渲染, WebView 的事件怎麼執行 JavascriptCore,接著往下看。

20191230235833.png

抹平WXML

wxml 是一種類 html 標記語言,他負責所有的渲染規則,包括條件渲染、列表渲染、數據綁定等,與其再實現一種框架,還不如直接利用 Vue 實現同樣的功能,再利用各種轉換庫將 wxml 中的事件轉換成 Vue 能夠識別的事件,如利用 post-html 可以做到如下的轉換:

20200101115533.png

每一個事件綁定的方法全都在原生的 JSContext 中運行,所以此時的事件只需要傳遞給 JSContext 的作用。

抹平WXSS

wxss 作為小程式的樣式語言,其餘 css 的主要區別就是多了一個 rpx 單位,以下是官網的換算表:
20200101120721.png
根據上表可得知, rpx = (750 / 屏幕寬度) * px;
在傳統的移動端頁面,我們的高清方案,一般需要獲取 dpr, 然後修改動態修改 viewport 和 html 上的 font-size,但是小程式的代碼因為是放在了設備本地,所以可以在下載小程式頁面之後,我們還有一次編譯機會,這時就可以把 rpx 根據當前設備的屏幕寬度替換成對應的 px。

還有一個 @import,則利用 scss 或 less 就可以合併到同一個 css 文件中,
而全局樣式則可以在構建 WXML 的時候再植入進入

抹平組件

組件具有獨特的功能和自己的渲染規則,比如 scroll-view 具有 scroll-xscroll-y 等屬性控制滾動條。在 HTML5 中有一個重大的功能web-component,它能夠自定義 html 元素,並且能夠監控屬性的變化,非常適合實現小程式組件。如:(使用了 lit-element 框架)

Untitled (1).jpeg

這裡用了 lit-element 這個框架,能夠簡化一些操作。

抹平 Page 和 App

App 負責整個應用的生命周期以及存一些全局的數據,getApp 能獲取到 app 的信息。 所以類似的結構可能是這樣的:

Untitled (4).jpeg

getApp 能夠直接訪問到內部對象,並且在最頂層聲明,這樣每一個的地方都能訪問到 getApp

初始化一個頁面都需要是實例化 PageClass, 即使再次進入(不是返回到這個頁面)這個頁面頁需要再次重新實例化,每次實例化都需要關聯一個 webviewId, 這個 ID 與原始的 webview 關聯,這樣每個 PageClass 中的 setData 都能找到對應的 webview 進行再次渲染,所以對應的代碼可能是這樣的:

Untitled (5).jpeg

抹平 API

通過 API 能夠直接調用原生的功能,比如 wx.request, 如果直接在 webview 中的 JSContext 中運行的話,則可能存在跨域,但是放在原生就不會存在這個問題。

實現JSContext 調用原生代碼的功能,需要給 JSContext 中植入一個 JSBridge,如: JSBridge.invokeJSBridge.on, invoke 負責同步任務,on 負責非同步任務,原生再利用反射(原生的反射真麻煩)調用對應的原生方法,原生可以利用 while(true) 掛起 JSContext,既可以達到同步和非同步的方法。

Untitled (3).jpeg

打包 Javascript

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

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

打包流程及其簡單,接下來看一下兩個 Javascript 引擎的交互過程。

打通 JSContext 到 WebView JavascriptCore

每次進入一個頁面的時候都需要為這個頁面的 webview 分配一個 id, 這個 id 至關重要,作為 native 與 JSContext (原生運行 javascript 的上下文對象) 與 webview 交互的唯一標識,JSContext 中需要實例化一個新的 PageClass 關聯這個 id, native 中通過 id 保留 webview 的引用。在 JSContext 中植入一個 JSBridge 用於與原生交互,如: JSBridge.setData(webviewId, appId, data), 當 JSBridge 的 setData 被調用後,通過 appId + webviewId 就能找到對應的 webview, 再將 setData 傳入 webview 中,在 Vue 接收到 data 後進行渲染, 整個過程如圖:

20200103232240.png

打通 Webview JavascriptCore 到 JSContext

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

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

Untitled (2).jpeg

結尾

利用原生作為橋梁,在兩個引擎之間通信,webview 中的 JSContext 負責接收渲染通知,以及發送事件到 Native 的 JSContext 中,JSContext 獨立運行,所以既訪問不到 window 對象,也訪問不到 document 對象。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 模擬命令行的界面效果,使用swoole作為websocket的服務,重新做了下html的界面效果 ...
  • 結構偽類選擇器介紹 結構偽類選擇器是用來處理一些特殊的效果。 結構偽類選擇器屬性說明表 屬性 | 描述 | E:first child | 匹配E元素的第一個子元素。 E:last child | 匹配E元素的最後一個子元素。 E:nth child(n) | 匹配E元素的第n個子元素。 E:nth ...
  • let只作用在當前塊級作用域內使用let或者const聲明的變數,不能再被重新聲明let不存在`變數提升` console.log(dad); var dad = '我是爸爸!';//預定義undefined console.log(dad); let dad = '我是爸爸!';//報錯 生成十個 ...
  • 組件化思想,包含: 下拉菜單項封裝 + 按需載入 搜索功能組件化,顯示數據 + 下拉顯示 + 緩存 分類導航按需載入 幻燈片效果組件封裝及按需載入 商品樓層模塊組件化 + 商品數據按需載入 + Tab選項卡 + 電梯結構 是時候放出大長圖了!!! index.html <!DOCTYPE html> ...
  • 第二個版本:點擊預約掛號可跳轉到排班表,獲取之後7個星期的排班 先放圖 首先是index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> <!-- 框架 --> <lin ...
  • 帶二級導航、輪播海報、二級聯動、搜索功能、Tab選項卡 按照國際慣例先放圖 index.html <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title>城市醫院預約平臺</title> <link rel=" ...
  • 尺寸和邊框: 一、尺寸 行內元素是不能設置寬和高的,其高度是由元素裡面的內容的高度撐起來的; 行內塊元素可以設置寬和高,當行內塊元素沒有設置寬高的時候,行內塊元素的寬高是其預設的寬高; 塊級元素:可以設置寬高,但是如果沒有設置寬,則其預設寬度是該塊級元素的父級元素的寬度的100%;如果沒有設置高度, ...
  • javascript正則表達式驗證IP地址的埠合法性(0-65535) ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...