亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

一種讓小程序支持JSX語法的新思路

Riddler / 2147人閱讀

摘要:下面我們介紹一種全新的處理思路,這種思路在小程序運(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 = Hello,然后把a賦值給了b,我們看下最新版本Taro 1.3的轉(zhuǎn)換,如下圖:

這個(gè)例子不是特別復(fù)雜,卻報(bào)錯(cuò)了。

要想理解上面的代碼為什么報(bào)錯(cuò),我們首先要理解編譯階段。本質(zhì)上來說在編譯階段,代碼其實(shí)就是‘字符串’,而編譯階段處理方案,就需要從這個(gè)‘字符串’中分析出必要的信息(通過AST,正則等方式)然后做對(duì)應(yīng)的等效轉(zhuǎn)換處理。

而對(duì)于上面的例子,需要做什么等效處理呢?需要我們?cè)?strong>編譯階段分析出bJSX片段:b = a = Hello,然后把中的等效替換為Hello。然而在編譯階段要想確定b的值是很困難的,有人說可以往前追溯來確定b的值,也不是不可以,但是考慮一下 由于b = a,那么就先要確定a的值,這個(gè)a的值怎么確定呢?需要在b可以訪問到的作用域鏈中確定a,然而a可能又是由其他變量賦值而來,循環(huán)往復(fù),期間一旦出現(xiàn)不是簡單賦值的情況,比如函數(shù)調(diào)用,三元判斷等運(yùn)行時(shí)信息,追溯就宣告失敗,要是a本身就是掛在全局對(duì)象上的變量,追溯就更加無從談起。

所以在編譯階段 是無法簡單確定b的值的。

我們?cè)僮屑?xì)看下上圖的報(bào)錯(cuò)信息:a is not defined。

為什么說a未定義呢?這是涉及到另外一個(gè)問題,我們知道Hello,其實(shí)等效于React.createElement(Text, null, "Hello"),而React.createElement方法的返回值就是一個(gè)普通JS對(duì)象,形如

// 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,所以Hello這個(gè)JSX片段被特殊處理了,a不再是一個(gè)普通js對(duì)象,這里我們看到a變量甚至丟失了,這里暴露了一個(gè)很嚴(yán)重的問題:代碼語義被破壞了,也就是說由于編譯時(shí)方案對(duì)JSX的特殊處理,真正運(yùn)行在小程序上的代碼語義并不是你的預(yù)期。這個(gè)是比較頭疼。

新的思路

正因?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文件