今天小編給大家分享一下如何讓小程序支持JSX語法的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
成都創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),雙柏企業(yè)網(wǎng)站建設(shè),雙柏品牌網(wǎng)站建設(shè),網(wǎng)站定制,雙柏網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,雙柏網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
現(xiàn)有思路的局限
在介紹新的思路之前,我們先來看下Taro(最新版1.3),nanachi是怎么在小程序端處理JSX語法的。簡(jiǎn)單來說,主要是通過在編譯階段把JSX轉(zhuǎn)化為等效的小程序wxml來把React代碼運(yùn)行在小程序端的。
舉個(gè)例子,比如React邏輯表達(dá)式:
xx &&
將會(huì)被轉(zhuǎn)化為等效的小程序wx:if指令:
這種方式把對(duì)JSX的處理,主要放在了編譯階段,他依賴于編譯階段的信息收集,以上面為例,它必須識(shí)別出邏輯表達(dá)式,然后做對(duì)應(yīng)的wx:if轉(zhuǎn)換處理。
那編譯階段有什么問題和局限呢?我們以下面的例子說明:
class App extends React.Component {
render () {
const a =
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è)诰幾g階段分析出b是JSX片段:b = a =
所以在編譯階段 是無法簡(jiǎn)單確定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)榫幾g時(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 =
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文件
注意這里每一個(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文件:
使用我們定制之后render執(zhí)行ReactDOM.render(
const uiDes = {
name: "000002",
child0001: {
name: 000001,
...
}
...
}
小程序獲取到這個(gè)uiDes,設(shè)置給占位模版。 最終渲染出小程序視圖。
在這整個(gè)過程中,你的所有JS代碼都是運(yùn)行在React過程中的,語義完全一致,JSX片段也不會(huì)被任何特殊處理,只是簡(jiǎn)單的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)閍 不過是普通對(duì)象。另外對(duì)于常見的編譯時(shí)方案的限制,比如任意函數(shù)返回JSX片段,動(dòng)態(tài)生成JSX片段,for循環(huán)使用JSX片段等等,都可以完全解除了,因?yàn)镴SX片段只是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ū)別。
以上就是“如何讓小程序支持JSX語法”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。