国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

Riddler / 2097人閱讀

摘要:下面我們介紹一種全新的處理思路,這種思路在小程序運行期間和真正的幾無區別,不會改變任何代碼語義,表達式只會被處理為方法調用,實際運行的時候就是普通對象,最終通過其他方式渲染出小程序視圖。最終渲染出小程序視圖。

React社區一直在探尋使用React語法開發小程序的方式,其中比較著名的項目有Taronanachi。而使用React語法開發小程序的難點主要就是在JSX語法上,JSX本質上是JS,相比于小程序靜態模版來說太靈活。本文所說的新思路就是在處理JSX語法上的新思路,這是一種更加動態的處理思路,相比于現有方案,基本上不會限制任何JSX的寫法,讓你以真正的React方式處理小程序,希望這個新思路可以給任何有志于用React開發小程序的人帶來啟發。

現有思路的局限

在介紹新的思路之前,我們先來看下Taro(最新版1.3)nanachi是怎么在小程序端處理JSX語法的。簡單來說,主要是通過在編譯階段JSX轉化為等效的小程序wxml來把React代碼運行在小程序端的。

舉個例子,比如React邏輯表達式:

xx && Hello

將會被轉化為等效的小程序wx:if指令:

Hello

這種方式把對JSX的處理,主要放在了編譯階段,他依賴于編譯階段信息收集,以上面為例,它必須識別出邏輯表達式,然后做對應的wx:if轉換處理。

編譯階段有什么問題和局限呢?我們以下面的例子說明:

class App extends React.Component {
    render () {
        const a = Hello
        const b = a

        return (
            
                {b}
            
        )
    }
}

首先我們聲明 const a = Hello,然后把a賦值給了b,我們看下最新版本Taro 1.3的轉換,如下圖:

這個例子不是特別復雜,卻報錯了。

要想理解上面的代碼為什么報錯,我們首先要理解編譯階段。本質上來說在編譯階段,代碼其實就是‘字符串’,而編譯階段處理方案,就需要從這個‘字符串’中分析出必要的信息(通過AST,正則等方式)然后做對應的等效轉換處理。

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

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

我們再仔細看下上圖的報錯信息:a is not defined

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

// ReactElement對象
{
   tag: Text,
   props: null,
   children: "Hello"
   ...
}

所以上面那一段代碼在JS環境真正運行的時候,大概等效如下:

class App extends React.Component {
    render () {
        const a = {
            tag: Text,
            props: null,
            children: "Hello"
            ...
        }
        const b = a

        return {
            tag: View,
            props: null,
            children: b
            ...
        }
    }
}

但是,我們剛說了編譯階段需要對JSX做等效處理,需要把JSX轉換為wxml,所以Hello這個JSX片段被特殊處理了,a不再是一個普通js對象,這里我們看到a變量甚至丟失了,這里暴露了一個很嚴重的問題:代碼語義被破壞了,也就是說由于編譯時方案對JSX的特殊處理,真正運行在小程序上的代碼語義并不是你的預期。這個是比較頭疼。

新的思路

正因為編譯時方案,有如上的限制,在使用的時候常常讓你有“我還是在寫React嗎?”這種感覺。

下面我們介紹一種全新的處理思路,這種思路在小程序運行期間和真正的React幾無區別,不會改變任何代碼語義,JSX表達式只會被處理為React.createElement方法調用,實際運行的時候就是普通js對象,最終通過其他方式渲染出小程序視圖。下面我們仔細說明一下這個思路的具體內容。

第一步:給每個獨立的JSX片段打上唯一標識uuid,假定我們有如下代碼:

const a = Hello

const y = 
    
    

我們給a片段,y片段 添加了uuid屬性

第二步:把React代碼通過babel轉義為小程序可以識別的代碼,例如JSX片段用等效的React.createElement替換等

const a = React.createElement(Text, {
  uuid: "000001"
}, "Hello");

第三步:提取每個獨立的JSX片段,用小程序template包裹,生成wxml文件