小程序的設計並無徹底遵循 Web 規範,致使小程序生態和傳統 Web 開發生態之間的割裂,海量優秀的 Web 物料並不能直接用於小程序開發。於是 Taro 在至關一段時間內生態都相對薄弱,UI 框架選擇很少的問題更是深深困擾着開發者。css
另外一方面,業界有着存量的 H5 應用,中短時間內 H5 應用適配到小程序端的須要還會存在。咱們但願能減小 H5 應用遷移到小程序端的成本,甚至可以直接運行在小程序端。html
Taro 團隊一直在思考如何最大限度地在小程序環境中複用 Web 生態,直到 Taro 3.0 誕生後,這種想法有了落地的可能。下文將介紹基於 Taro 3.0 實現 H5 同構的思路與問題,以及咱們嘗試適配了三大移動端 UI 框架 WEUI、Ant Design Mobile、VantUI 的實驗結果。前端
Taro 3.0 是一款重運行時的跨端框架,它經過模擬實現瀏覽器的 BOM 和 DOM API 實現了對 React、Vue 等 Web 開發框架的兼容。html5
既然已經有了瀏覽器環境的 BOM 和 DOM API,Taro 應用和 Web 應用之間的鴻溝在於小程序組件和 HTML 標籤之間的差別。node
<!--truncate-->git
Taro3 的渲染數據流以下:github
前端框架 -> Taro DOM -> 小程序 datanpm
HTML 標籤和小程序組件的標籤名、屬性、事件是有差別的,而前端框架無需感知這些差別。json
所以前端框架適配層、Taro DOM 層不須要改動,只要在 Taro DOM 序列化爲小程序 data 這一步做映射便可。canvas
HTML 標籤相對小程序組件封裝程度更低、功能更簡單,能夠看做是小程序組件的子集。所以能夠按必定的規則,把 HTML 標籤映射爲小程序組件,如:
// Taro DOM 的序列化數據 { nn: 'img' } // 映射結果 { nn: 'image' }
完整的標籤名映射規則請看:RFC 附錄一
若是 HTML 標籤的屬性能在對應小程序組件的屬性上找到對應,則進行映射,如:
// Taro DOM 的序列化數據 { nn: 'a', href: 'xxx' target: '_blank' } // 映射結果 { nn: 'navigator', url: 'xxx', openType: 'navigate' }
完整的屬性名映射規則請看:RFC 附錄二
把 HTML 特有的事件在小程序端找到類似的事件進行映射,如:
HTML 事件 | 小程序組件事件 |
---|---|
click | tap |
完整的事件映射規則請看:RFC 附錄三
前文介紹了咱們會把 HTML 標籤映射爲小程序組件,可是 H5 應用中使用到的 CSS 標籤選擇器就會失效。
所以 Taro 使用了類名去進行模擬:
1) 爲全部 H5 標籤都加上類名: h5-${tagName}
。
// 源代碼 <div /> // 渲染結果 <view class="h5-div" />
2) 使用 postcss 插件處理標籤名選擇器:
// 標籤名選擇器 div {} // 經 postcss 插件處理後變爲類名選擇器 .h5-div {}
Taro 提供兩種內置的瀏覽器默認樣式,能夠直接引入生效:
@tarojs/taro/html.css
: W3C HTML4 的內置樣式。只有 HTML4 標籤樣式,體積較小,兼容性強,能適應大多數狀況。@tarojs/taro/html5.css
: Chrome(Blink) HTML5 的內置樣式。內置樣式豐富,包括了大多數 HTML5 標籤,體積較大,不必定支持全部小程序容器。理想很美好,但現實卻略顯骨感。即便 Taro 能實現 BOM、DOM API,支持使用 HTML 標籤等,同構方案仍是存在着一些框架層面抹平不了的差別。如下列舉出若干主要限制:
在 H5 中咱們能夠調用 DOM API 同步獲取元素的尺寸:
// h5 const el = document.getElementById('#inner') const res = el.getBoundingClientRect() console.log(res)
可是在小程序中,獲取元素尺寸的 API 是異步的:
// 小程序 const query = Taro.createSelectorQuery() query.select('#inner') .boundingClientRect() .exec(res => { console.log(res) })
所以不能兼容那些使用了同步 DOM API 去獲取元素尺寸的組件。
<canvas>
、<video>
、<audio>
等標籤在 H5 端能夠直接調用 HTMLElement
上的方法:
// h5 const el = document.getElementById('myVideo') el.play()
可是在 Taro 中,要調用組件上的原生方法,必須先建立對應的 Context
:
// 小程序 const ctx = Taro.createVideoContext('myVideo') ctx.play()
部分樣式或 CSS 選擇器在小程序中不支持,如:
首先須要安裝 v3.3 的 CLI 工具:
npm i -g @tarojs/cli@alpha
而後進入項目,把 package.json
文件中 taro 相關依賴的版本修改成 ^3.3.0-alpha.2
,再從新安裝依賴(建議先把 node_modules 文件夾刪除)。
爲了節省項目空間,同構功能是可選的,以 Taro 插件的形式提供。
首先開發者須要安裝插件 @tarojs/plugin-html
:
npm i @tarojs/plugin-html
而後配置使用此插件:
// config/index.js const config = { // ... plugins: [ '@tarojs/plugin-html' ] }
爲了驗證同構功能的可用性和效果,咱們對 CSS 樣式庫 WEUI、React 組件庫 Antd Design Mobile、Vue2 組件庫 VantUI 的全部組件進行了測試。
測試效果比較理想,甚至稍微超出咱們的預期,配合各組件庫自身的按需加載能力,能以小巧的體積使用豐富的組件,相信各位開發者會喜歡這個功能。
倉庫地址:taro-weui
WEUI 是一個 CSS 的樣式庫,與框架無關,兼容性比較高,大部分組件能直接使用。
倉庫地址:taro-antd-mobile
Antd Mobile Design 官方已經至關久沒有維護,此適配項目屬於實驗性質。
能直接兼容使用的組件大概爲 80%,主要問題在於:
倉庫地址:taro-vant
VantUI 的組件十分豐富,能直接兼容使用的組件大概爲 70%。部分開發者會在 Taro 中配合使用 Vant Weapp,但 Vant Weapp 只能運行在微信小程序,所以對 VantUI 的直接適配是一個很好的補充。
適配過程主要遇到的問題有:
<transition>
組件須要額外適配。同構方案還在持續優化中,部分實現尚未最終定稿。歡迎各位開發者到咱們的論壇下留言,提出您的寶貴意見~:同構方案 RFC。
歡迎關注凹凸實驗室博客:aotu.io
或者關注凹凸實驗室公衆號(AOTULabs),不定時推送文章。