摘要:下面我們介紹一種全新的處理思路,這種思路在小程序運(yùn)行期間和真正的幾無區(qū)別,不會(huì)改變?nèi)魏未a語義,表達(dá)式只會(huì)被處理為方法調(diào)用,實(shí)際運(yùn)行的時(shí)候就是普通對(duì)象,最終通過其他方式渲染出小程序視圖。最終渲染出小程序視圖。
React社區(qū)一直在探尋使用React語法開發(fā)小程序的方式,其中比較著名的項(xiàng)目有Taro,nanachi。而使用React語法開發(fā)小程序的難點(diǎn)主要就是在JSX語法上,JSX本質(zhì)上是JS,相比于小程序靜態(tài)模版來說太靈活。本文所說的新思路就是在處理JSX語法上的新思路,這是一種更加動(dòng)態(tài)的處理思路,相比于現(xiàn)有方案,基本上不會(huì)限制任何JSX的寫法,讓你以真正的React方式處理小程序,希望這個(gè)新思路可以給任何有志于用React開發(fā)小程序的人帶來啟發(fā)。
現(xiàn)有思路的局限在介紹新的思路之前,我們先來看下Taro(最新版1.3),nanachi是怎么在小程序端處理JSX語法的。簡單來說,主要是通過在編譯階段把JSX轉(zhuǎn)化為等效的小程序wxml來把React代碼運(yùn)行在小程序端的。
舉個(gè)例子,比如React邏輯表達(dá)式:
xx &&Hello
將會(huì)被轉(zhuǎn)化為等效的小程序wx:if指令:
Hello
這種方式把對(duì)JSX的處理,主要放在了編譯階段,他依賴于編譯階段的信息收集,以上面為例,它必須識(shí)別出邏輯表達(dá)式,然后做對(duì)應(yīng)的wx:if轉(zhuǎn)換處理。
那編譯階段有什么問題和局限呢?我們以下面的例子說明:
class App extends React.Component { render () { const a =Hello const b = a return () } }
首先我們聲明 const a =
這個(gè)例子不是特別復(fù)雜,卻報(bào)錯(cuò)了。
要想理解上面的代碼為什么報(bào)錯(cuò),我們首先要理解編譯階段。本質(zhì)上來說在編譯階段,代碼其實(shí)就是‘字符串’,而編譯階段處理方案,就需要從這個(gè)‘字符串’中分析出必要的信息(通過AST,正則等方式)然后做對(duì)應(yīng)的等效轉(zhuǎn)換處理。
而對(duì)于上面的例子,需要做什么等效處理呢?需要我們?cè)?strong>編譯階段分析出b是JSX片段:b = a =
所以在編譯階段 是無法簡單確定b的值的。
我們?cè)僮屑?xì)看下上圖的報(bào)錯(cuò)信息:a is not defined。
為什么說a未定義呢?這是涉及到另外一個(gè)問題,我們知道
// ReactElement對(duì)象 { tag: Text, props: null, children: "Hello" ... }
所以上面那一段代碼在JS環(huán)境真正運(yùn)行的時(shí)候,大概等效如下:
class App extends React.Component { render () { const a = { tag: Text, props: null, children: "Hello" ... } const b = a return { tag: View, props: null, children: b ... } } }
但是,我們剛說了編譯階段需要對(duì)JSX做等效處理,需要把JSX轉(zhuǎn)換為wxml,所以
正因?yàn)?strong>編譯時(shí)方案,有如上的限制,在使用的時(shí)候常常讓你有“我還是在寫React嗎?”這種感覺。
下面我們介紹一種全新的處理思路,這種思路在小程序運(yùn)行期間和真正的React幾無區(qū)別,不會(huì)改變?nèi)魏未a語義,JSX表達(dá)式只會(huì)被處理為React.createElement方法調(diào)用,實(shí)際運(yùn)行的時(shí)候就是普通js對(duì)象,最終通過其他方式渲染出小程序視圖。下面我們仔細(xì)說明一下這個(gè)思路的具體內(nèi)容。
第一步:給每個(gè)獨(dú)立的JSX片段打上唯一標(biāo)識(shí)uuid,假定我們有如下代碼:
const a =Hello const y =
我們給a片段,y片段 添加了uuid屬性
第二步:把React代碼通過babel轉(zhuǎn)義為小程序可以識(shí)別的代碼,例如JSX片段用等效的React.createElement替換等
const a = React.createElement(Text, { uuid: "000001" }, "Hello");
第三步:提取每個(gè)獨(dú)立的JSX片段,用小程序template包裹,生成wxml文件
Hello
注意這里每一個(gè)template 的name標(biāo)識(shí)和 JSX片段的唯一標(biāo)識(shí)uuid是一樣的。最后,需要在結(jié)尾生成一個(gè)占位模版:。
第四步:修改ReactDOM.render的遞歸(React 16.x之后,不在是遞歸的方式)過程,遞歸執(zhí)行階段,聚合JSX片段的uuid屬性,生成并返回uiDes數(shù)據(jù)結(jié)構(gòu)。
第五步:把第四步生成的uiDes,傳遞給小程序環(huán)境,小程序把uiDes 設(shè)置給占位模版,渲染出最終的視圖。
我們以上面的App組件的例子來說明整個(gè)過程,首先js代碼會(huì)被轉(zhuǎn)義為:
class App extends React.Component { render () { const a = React.createElement(Text, {uuid: "000001"}, "Hello"); const b = a return ( React.createElement(View, {uuid: "000002"} , b); ) } }
同時(shí)生成wxml文件:
Hello
使用我們定制之后render執(zhí)行ReactDOM.render(
const uiDes = { name: "000002", child0001: { name: 000001, ... } ... }
小程序獲取到這個(gè)uiDes,設(shè)置給占位模版。 最終渲染出小程序視圖。
在這整個(gè)過程中,你的所有JS代碼都是運(yùn)行在React過程中的,語義完全一致,JSX片段也不會(huì)被任何特殊處理,只是簡單的React.createElement調(diào)用,另外由于這里的React過程只是純js運(yùn)算,執(zhí)行是非常迅速的,通常只有幾ms。最終會(huì)輸出一個(gè)uiDes數(shù)據(jù)到小程序,小程序通過這個(gè)uiDes渲染出視圖。
現(xiàn)在我們?cè)诳粗暗馁x值const b = a,就不會(huì)有任何問題了,因?yàn)?b>a 不過是普通對(duì)象。另外對(duì)于常見的編譯時(shí)方案的限制,比如任意函數(shù)返回JSX片段,動(dòng)態(tài)生成JSX片段,for循環(huán)使用JSX片段等等,都可以完全解除了,因?yàn)?b>JSX片段只是js對(duì)象,你可以做任何操作,最終ReactDOM.render會(huì)搜集所有執(zhí)行結(jié)果的片段的uuid標(biāo)識(shí),生成uiDes,而小程序會(huì)根據(jù)這個(gè)uiDes數(shù)據(jù)結(jié)構(gòu)渲染出最終視圖。
可以看出這種新的思路和以前編譯時(shí)方案還是有很大的區(qū)別的,對(duì)JSX片段的處理是動(dòng)態(tài)的,你可以在任何地方,任何函數(shù)出現(xiàn)任何JSX片段, 最終執(zhí)行結(jié)果會(huì)確定渲染哪一個(gè)片段,只有執(zhí)行結(jié)果的片段的uuid會(huì)被寫入uiDes。這和編譯時(shí)方案的靜態(tài)識(shí)別有著本質(zhì)的區(qū)別。
結(jié)語"Talk is cheap. Show me your code!" 這僅僅是一個(gè)思路?還是已經(jīng)有落地完整的實(shí)現(xiàn)呢?
是有完整的實(shí)現(xiàn)的,alita項(xiàng)目在處理JSX語法的時(shí)候,采用的就是這個(gè)思路,這也是alita基本不限制寫法卻可以轉(zhuǎn)化整個(gè)React Native項(xiàng)目的原因,另外alita在這個(gè)思路上做了很多優(yōu)化。如果對(duì)這個(gè)思路的具體實(shí)現(xiàn)有興趣,可以去研讀一下alita源碼,它完全是開源的https://github.com/areslabs/alita。
當(dāng)然,你也可以基于這個(gè)思路,構(gòu)造出自己的React小程序開發(fā)方案。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/104739.html
摘要:介紹是內(nèi)部的一個(gè)類庫并開源,可用于創(chuàng)建用戶交互界面。主要有四個(gè)主要概念構(gòu)成,下面分別來簡單介紹一下之所以引入虛擬,一方面是性能的考慮。允許直接在模板插入變量。這種單向數(shù)據(jù)流使得整個(gè)系統(tǒng)都是透明可預(yù)測(cè)的。 React 介紹 React是Facrbook內(nèi)部的一個(gè)JavaScript類庫并開源,可用于創(chuàng)建Web用戶交互界面。它引入了一種新的方式來處理瀏覽器DOM。那些需要手動(dòng)更新DOM、費(fèi)...
摘要:是的語法,截止我寫這篇文章為止,小程序還是不支持語法的,所以需要使用這個(gè)庫下載,并把文件夾放到目錄下在引入封裝,讓微信的支持語法所有的請(qǐng)求,默認(rèn)攜帶可以控制是否顯示加載狀態(tài)加載中封裝好后就可以在文件中使用了,使用方法如下請(qǐng) async-await是ES7的語法,截止我寫這篇文章為止,小程序還是不支持async-await語法的,所以需要使用regenerator這個(gè)庫 下載regene...
摘要:官方規(guī)范估計(jì)很難出現(xiàn)現(xiàn)代框架的設(shè)計(jì)了,因?yàn)楣俜皆O(shè)計(jì)中前端三劍客是相互分離的方案,為了解決現(xiàn)階段前端框架的問題,必須由完全接管,這幾乎就是,或者支持語法的,可這與最初網(wǎng)頁設(shè)計(jì)思路是違背的?,F(xiàn)代前端框架正在告訴我們新的三劍客虛擬虛擬。 1 引言 深入思考為何前端需要框架,以及 web components 是否可以代替前端框架? 原文地址,建議先閱讀原文,或者閱讀概述。 2 概述 現(xiàn)在前端...
摘要:也可以安裝瀏覽器插件或,在某個(gè)文件的網(wǎng)頁上就能看到一個(gè)的按鈕,點(diǎn)擊即可。 【AIS-TXD前端技術(shù)月刊】- 本月熱門前端技術(shù)快報(bào),匯聚 Github Trending 流行 Repo 和熱門文章,文末有福利 showImg(https://segmentfault.com/img/remote/1460000018406928?w=1352&h=808); 歡迎?訂閱?&?投稿本期小編...
閱讀 2531·2021-11-17 09:33
閱讀 832·2021-11-04 16:13
閱讀 1388·2021-10-14 09:50
閱讀 743·2019-08-30 15:53
閱讀 3727·2019-08-30 14:18
閱讀 3319·2019-08-30 14:14
閱讀 2157·2019-08-30 12:46
閱讀 3234·2019-08-26 14:05