<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        詳解如何用babel轉換es6的class語法

        來源:懂視網 責編:小采 時間:2020-11-27 22:16:59
        文檔

        詳解如何用babel轉換es6的class語法

        詳解如何用babel轉換es6的class語法:babel是一個轉碼器,目前開發react、vue項目都要使用到它。它可以把es6+的語法轉換為es5,也可以轉換JSX等語法。 我們在項目中都是通過配置插件和預設(多個插件的集合)來轉換特定代碼,例如env、stage-0等。 實際上babel可以通過自定義插件的方式實現任何
        推薦度:
        導讀詳解如何用babel轉換es6的class語法:babel是一個轉碼器,目前開發react、vue項目都要使用到它。它可以把es6+的語法轉換為es5,也可以轉換JSX等語法。 我們在項目中都是通過配置插件和預設(多個插件的集合)來轉換特定代碼,例如env、stage-0等。 實際上babel可以通過自定義插件的方式實現任何

        babel是一個轉碼器,目前開發react、vue項目都要使用到它。它可以把es6+的語法轉換為es5,也可以轉換JSX等語法。

        我們在項目中都是通過配置插件和預設(多個插件的集合)來轉換特定代碼,例如env、stage-0等。

        實際上babel可以通過自定義插件的方式實現任何代碼的轉換,接下來我們通過一個“把es6的 class 轉換為es5”的例子來了解一下babel。

        內容如下:

        webpack環境配置

        大家應該都配置過babel-core這個loader,它的作用是提供babel的核心Api,實際上我們的代碼轉換都是通過插件來實現的。

        接下來我們不用第三方的插件,自己實現一個es6類轉換插件。先執行以下幾步初始化一個項目:

        1. npm install webpack webpack-cli babel-core -D
        2. 新建一個webpack.config.js
        3. 配置webpack.config.js

        如果我們的插件名字想叫transform-class,需要在webpack配置中做如下配置:

        接下來我們在node_modules中新建一個babel-plugin-transform-class的文件夾來寫插件的邏輯(如果是真實項目,你需要編寫這個插件并發布到npm倉庫),如下圖:

        紅色區域是我新建的文件夾,它上面的是一個標準的插件的項目結構,為了方便我只寫了核心的index.js文件。

        如何編寫bable插件

        babel插件其實是通過AST(抽象語法樹)實現的。

        babel幫助我們把js代碼轉換為AST,然后允許我們修改,最后再把它轉換成js代碼。

        那么就涉及到兩個問題:js代碼和AST之間的映射關系是什么?如何替換或者新增AST?

        好,先介紹一個工具:astexplorer.net:

        這個工具可以把一段代碼轉換為AST:

        如圖,我們寫了一個es6的類,然后網頁的右邊幫我們生成了一個AST,其實就是把每一行代碼變成了一個對象,這樣我們就實現了一個映射。

        再介紹一個文檔: babel-types :

        這是創建AST節點的api文檔。

        比如,我們想創建一個類,先到astexplorer.net中轉換,發現類對應的AST類型是 ClassDeclaration 。好,我們去文檔中搜索,發現調用下面的api就可以了:

        創建其他語句也是一樣的道理,有了上面這兩個東西,我們可以做任何轉換了。

        下面我們開始真正編寫一個插件,分為以下幾步:

        1. 在index.js中export一個函數
        2. 函數中返回一個對象,對象有一個visitor參數(必須叫visitor)
        3. 通過astexplorer.net查詢出 class 對應的AST節點為 ClassDeclaration
        4. 在vistor中設置一個捕獲函數 ClassDeclaration ,意思是我要捕獲js代碼中所有 ClassDeclaration 節點
        5. 編寫邏輯代碼,完成轉換
        module.exports = function ({ types: t }) {
         return {
         visitor: {
         ClassDeclaration(path) {
         //在這里完成轉換
         }
         }
         };
        }

        代碼中有兩個參數,第一個 {types:t} 東西是從參數中解構出變量t,它其實就是babel-types文檔中的t(下圖紅框),它是用來創建節點的:

        第二個參數 path ,它是捕獲到的節點對應的信息,我們可以通過 path.node 獲得這個節點的AST,在這個基礎上進行修改就能完成了我們的目標。

        如何把es6的class轉換為es5的類

        上面都是預備工作,真正的邏輯從現在才開始,我們先考慮兩個問題:

        我們要做如下轉換,首先把es6的類,轉換為es5的類寫法(也就是普通函數),我們觀察到,很多代碼是可以復用的,包括函數名字、函數內部的代碼塊等。

         

        如果不定義class中的 constructor 方法,JavaScript引擎會自動為它添加一個空的 constructor() 方法,這需要我們做兼容處理。

        接下來我們開始寫代碼,思路是:

        1. 拿到老的AST節點
        2. 創建一個數組用來盛放新的AST節點(雖然原class只是一個節點,但是替換后它會被若干個函數節點取代) 初始化默認的 constructor 節點(上文提到,class中有可能沒有定義constructor)
        3. 循環老節點的AST對象(會循環出若干個函數節點)
        4. 判斷函數的類型是不是 constructor ,如果是,通過取到數據創建一個普通函數節點,并更新默認 constructor 節點
        5. 處理其余不是 constructor 的節點,通過數據創建 prototype 類型的函數,并放到 es5Fns
        6. 循環結束,把 constructor 節點也放到 es5Fns
        7. 判斷es5Fns的長度是否大于1,如果大于1使用 replaceWithMultiple 這個API更新AST
        module.exports = function ({ types: t }) {
         return {
         visitor: {
         ClassDeclaration(path) {
         //拿到老的AST節點
         let node = path.node
         let className = node.id.name
         let classInner = node.body.body
         //創建一個數組用來成盛放新生成AST
         let es5Fns = []
         //初始化默認的constructor節點
         let newConstructorId = t.identifier(className)
         let constructorFn = t.functionDeclaration(newConstructorId, [t.identifier('')], t.blockStatement([]), false, false)
         //循環老節點的AST對象
         for (let i = 0; i < classInner.length; i++) {
         let item = classInner[i]
         //判斷函數的類型是不是constructor
         if (item.kind == 'constructor') {
         let constructorParams = item.params.length ? item.params[0].name : []
         let newConstructorParams = t.identifier(constructorParams)
         let constructorBody = classInner[i].body
         constructorFn = t.functionDeclaration(newConstructorId, [newConstructorParams], constructorBody, false, false)
         } 
         //處理其余不是constructor的節點
         else {
         let protoTypeObj = t.memberExpression(t.identifier(className), t.identifier('prototype'), false)
         let left = t.memberExpression(protoTypeObj, t.identifier(item.key.name), false)
         //定義等號右邊
         let prototypeParams = classInner[i].params.length ? classInner[i].params[i].name : []
         let newPrototypeParams = t.identifier(prototypeParams)
         let prototypeBody = classInner[i].body
         let right = t.functionExpression(null, [newPrototypeParams], prototypeBody, false, false)
         let protoTypeExpression = t.assignmentExpression("=", left, right)
         es5Fns.push(protoTypeExpression)
         }
        
         }
         //循環結束,把constructor節點也放到es5Fns中
         es5Fns.push(constructorFn)
         //判斷es5Fns的長度是否大于1
         if (es5Fns.length > 1) {
         path.replaceWithMultiple(es5Fns)
         } else {
         path.replaceWith(constructorFn)
         }
         }
         }
         };
        }

        優化繼承

        其實,類還涉及到繼承,思路也不復雜,就是判斷AST中沒有 superClass 屬性,如果有的話,我們需要多添加一行代碼 Bird.prototype = Object.create(Parent) ,當然別忘了處理 super 關鍵字。

        打包后代碼

         

        運行 npm start 打包后,我們看到打包后的文件里 class

        語法已經成功轉換為一個個的es5函數。

        結尾

        現在一個類轉換器就寫完了,希望能對大家了解babel有一點幫助。也希望大家多多支持腳本之家。

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        詳解如何用babel轉換es6的class語法

        詳解如何用babel轉換es6的class語法:babel是一個轉碼器,目前開發react、vue項目都要使用到它。它可以把es6+的語法轉換為es5,也可以轉換JSX等語法。 我們在項目中都是通過配置插件和預設(多個插件的集合)來轉換特定代碼,例如env、stage-0等。 實際上babel可以通過自定義插件的方式實現任何
        推薦度:
        標簽: 轉換 如何 語法
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲视频精品在线| 亚洲人成电影在线天堂| 亚洲国产日韩综合久久精品| www视频在线观看免费| 亚洲精品视频观看| 亚洲精品视频在线免费| 亚洲国产福利精品一区二区| 麻豆最新国产剧情AV原创免费| 亚洲国产精品综合一区在线 | 精品亚洲视频在线观看| 黄色毛片视频免费| 久久久久亚洲AV成人网人人网站| 一区二区三区免费视频播放器 | 国产亚洲综合久久系列| 无码精品国产一区二区三区免费 | 在线免费观看国产视频| 美女视频黄.免费网址| 激情综合色五月丁香六月亚洲| 国内精品99亚洲免费高清| 亚洲高清视频在线观看| 久久成人国产精品免费软件| 亚洲熟妇无码一区二区三区| 免费**毛片在线播放直播| 你是我的城池营垒免费观看完整版 | 亚洲国产精品无码久久九九大片| 日韩免费a级在线观看| 一个人免费观看视频在线中文| 亚洲色无码专区在线观看| 69天堂人成无码麻豆免费视频| 亚洲AV成人精品日韩一区| 亚洲综合色婷婷七月丁香| 120秒男女动态视频免费| 亚洲爆乳无码精品AAA片蜜桃| 国产亚洲精品不卡在线| 亚洲美女免费视频| 男男黄GAY片免费网站WWW| 久久亚洲AV午夜福利精品一区| 成人无遮挡裸免费视频在线观看| 免费人成视频在线| 国产精品hd免费观看| 亚洲理论片在线中文字幕|