最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2019年06月16日 10:20:23   作者:ykforerlang  
這篇文章主要介紹了淺談一種讓小程序支持JSX語法的新思路,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

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

現(xiàn)有思路的局限

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

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

xx && <Text>Hello</Text>

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

<Text wx:if="{{xx}}">Hello</Text>

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

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

class App extends React.Component {
  render () {
    const a = <Text>Hello</Text>
    const b = a

    return (
      <View>
        
      </View>
    )
  }
}

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

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

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

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

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

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

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

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

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

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

新的思路

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

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

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

const a = <Text uuid="000001">Hello</Text>

const y = <View uuid="000002">
  <Image/>
  <Text/>
</View>

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

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

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

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

<template name="000001">
  <Text>Hello</Text>
</template>

<template name="000002">
  <View uuid="000002">
    <Image/>
    <Text/>
  </View>
</template>


<!--占位template-->
<template is="{{uiDes.name}}" data="{{...uiDes}}"/>

注意這里每一個templatename標識和 JSX片段的唯一標識uuid是一樣的。最后,需要在結尾生成一個占位模版:<template is="{{uiDes.name}}" data="{{...uiDes}}"/>。

第四步:修改ReactDOM.render的遞歸(React 16.x之后,不在是遞歸的方式)過程,遞歸執(zhí)行階段,聚合JSX片段的uuid屬性,生成并返回uiDes數(shù)據(jù)結構。

第五步:把第四步生成的uiDes,傳遞給小程序環(huán)境,小程序把uiDes 設置給占位模版<template is="{{uiDes.name}}" data="{{...uiDes}}"/>,渲染出最終的視圖。

我們以上面的App組件的例子來說明整個過程,首先js代碼會被轉義為:

class App extends React.Component {
  render () {
    const a = React.createElement(Text, {uuid: "000001"}, "Hello");
    const b = a
    
    return (
     React.createElement(View, {uuid: "000002"} , b);
    )
   }
}

同時生成wxml文件:

<template name="000001">
  <Text>Hello</Text>
</template>

<template name="000002">
  <View>
    <template is="{{child0001.name}}" data="{{...child0001}}"/>
  </View>
</template>

<!--占位template-->
<template is="{{uiDes.name}}" data="{{...uiDes}}"/>

使用我們定制之后render執(zhí)行ReactDOM.render(<App/>, parent)。在render的遞歸過程中,除了會執(zhí)行常規(guī)的創(chuàng)建組件實例,執(zhí)行生命周期之外,還會額外的收集執(zhí)行過程中組件的uuid標識,最終生成 uiDes 對象

const uiDes = {
  name: "000002",
  
  child0001: {
      name: 000001,
      ...
  }
  
  ...
}

小程序獲取到這個uiDes,設置給占位模版<template is="{{uiDes.name}}" data="{{...uiDes}}"/>。 最終渲染出小程序視圖。

在這整個過程中,你的所有JS代碼都是運行在React過程中的,語義完全一致,JSX片段也不會被任何特殊處理,只是簡單的React.createElement調用,另外由于這里的React過程只是純js運算,執(zhí)行是非常迅速的,通常只有幾ms。最終會輸出一個uiDes數(shù)據(jù)到小程序,小程序通過這個uiDes渲染出視圖。

現(xiàn)在我們在看之前的賦值const b = a,就不會有任何問題了,因為a 不過是普通對象。另外對于常見的編譯時方案的限制,比如任意函數(shù)返回JSX片段,動態(tài)生成JSX片段,for循環(huán)使用JSX片段等等,都可以完全解除了,因為JSX片段只是js對象,你可以做任何操作,最終ReactDOM.render會搜集所有執(zhí)行結果的片段的uuid標識,生成uiDes,而小程序會根據(jù)這個uiDes數(shù)據(jù)結構渲染出最終視圖。

可以看出這種新的思路和以前編譯時方案還是有很大的區(qū)別的,對JSX片段的處理是動態(tài)的,你可以在任何地方,任何函數(shù)出現(xiàn)任何JSX片段, 最終執(zhí)行結果會確定渲染哪一個片段,只有執(zhí)行結果的片段的uuid會被寫入uiDes。這和編譯時方案的靜態(tài)識別有著本質的區(qū)別。

結語

"Talk is cheap. Show me your code!" 這僅僅是一個思路?還是已經(jīng)有落地完整的實現(xiàn)呢?

是有完整的實現(xiàn)的,alita項目在處理JSX語法的時候,采用的就是這個思路,這也是alita基本不限制寫法卻可以轉化整個React Native項目的原因,另外alita在這個思路上做了很多優(yōu)化。如果對這個思路的具體實現(xiàn)有興趣,可以去研讀一下alita源碼,它完全是開源的https://github.com/areslabs/alita。

當然,你也可以基于這個思路,構造出自己的React小程序開發(fā)方案。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • 微信小程序跳轉外部鏈接的詳細實現(xiàn)方法

    微信小程序跳轉外部鏈接的詳細實現(xiàn)方法

    寫這個是因為最近小程序的一個需求需要從小程序跳轉到客戶的官網(wǎng),或者其他外部報名鏈接,下面這篇文章主要給大家介紹了關于微信小程序跳轉外部鏈接的詳細實現(xiàn)方法,需要的朋友可以參考下
    2022-10-10
  • JavaScript 對象模型 執(zhí)行模型

    JavaScript 對象模型 執(zhí)行模型

    簡單數(shù)值類型: 有Undefined, Null, Boolean, Number和String。注意,描述中的英文單詞在這里僅指數(shù)據(jù)類型的名稱,并不特指JS的全局對象N an, Boolean, Number, String等,它們在概念上的區(qū)別是比較大的。
    2010-10-10
  • 值得學習的JavaScript調試技巧分享

    值得學習的JavaScript調試技巧分享

    這篇文章主要給大家介紹了一些JavaScript調試技巧,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • 看看“疫苗查詢”小程序有溫度的代碼

    看看“疫苗查詢”小程序有溫度的代碼

    近日,一篇《疫苗之王》刷爆了朋友圈,疫苗的安全問題被推到了風口浪尖,騰訊安全反詐實驗室團隊推出了“騰訊安心計劃”小程序,方便用戶便捷地查詢疫苗安全信
    2018-07-07
  • javascript CSS畫圖之基礎篇

    javascript CSS畫圖之基礎篇

    要在瀏覽器上動態(tài)地畫圖(矢量圖),個人覺得矢量圖中最關鍵的兩點.
    2009-07-07
  • 點擊進行復制的JS代碼實例

    點擊進行復制的JS代碼實例

    這篇文章介紹了點擊進行復制的JS代碼實例,有需要的朋友可以參考一下
    2013-08-08
  • 原生JS實現(xiàn)九宮格抽獎效果

    原生JS實現(xiàn)九宮格抽獎效果

    本篇文章主要介紹了原生JS實現(xiàn)九宮格抽獎效果的示例代碼。具有很好的參考價值。下面跟著小編一起來看下吧
    2017-04-04
  • JS生態(tài)系統(tǒng)加速模塊解析賦能性能優(yōu)化探索

    JS生態(tài)系統(tǒng)加速模塊解析賦能性能優(yōu)化探索

    這篇文章主要為大家介紹了JS生態(tài)系統(tǒng)加速模塊解析賦能性能優(yōu)化探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • es6函數(shù)之嚴格模式用法實例分析

    es6函數(shù)之嚴格模式用法實例分析

    這篇文章主要介紹了es6函數(shù)之嚴格模式用法,結合實例形式分析了es6函數(shù)嚴格模式的定義、用法及操作注意事項,需要的朋友可以參考下
    2020-03-03
  • JS按鈕閃爍功能的實現(xiàn)代碼

    JS按鈕閃爍功能的實現(xiàn)代碼

    js按鈕閃爍功能的實現(xiàn)代碼分為html和js兩部分代碼,具體實現(xiàn)代碼大家參考下本文
    2017-07-07

最新評論

呼图壁县| 南宁市| 汉源县| 兴宁市| 喀喇沁旗| 谢通门县| 报价| 安宁市| 阳江市| 屏南县| 商河县| 威海市| 海宁市| 民和| 江安县| 肥乡县| 陆川县| 莒南县| 旺苍县| 土默特右旗| 融水| 隆回县| 吐鲁番市| 确山县| 禹州市| 思茅市| 四川省| 惠东县| 揭西县| 上犹县| 色达县| 临武县| 柘荣县| 涿鹿县| 丹凤县| 宁津县| 巴林右旗| 五大连池市| 嵩明县| 汝南县| 高台县|