• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題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關(guān)鍵字專題關(guān)鍵字專題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
    當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

    詳解如何用babel轉(zhuǎn)換es6的class語(yǔ)法

    來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 22:16:59
    文檔

    詳解如何用babel轉(zhuǎn)換es6的class語(yǔ)法

    詳解如何用babel轉(zhuǎn)換es6的class語(yǔ)法:babel是一個(gè)轉(zhuǎn)碼器,目前開發(fā)react、vue項(xiàng)目都要使用到它。它可以把es6+的語(yǔ)法轉(zhuǎn)換為es5,也可以轉(zhuǎn)換JSX等語(yǔ)法。 我們?cè)陧?xiàng)目中都是通過配置插件和預(yù)設(shè)(多個(gè)插件的集合)來(lái)轉(zhuǎn)換特定代碼,例如env、stage-0等。 實(shí)際上babel可以通過自定義插件的方式實(shí)現(xiàn)任何
    推薦度:
    導(dǎo)讀詳解如何用babel轉(zhuǎn)換es6的class語(yǔ)法:babel是一個(gè)轉(zhuǎn)碼器,目前開發(fā)react、vue項(xiàng)目都要使用到它。它可以把es6+的語(yǔ)法轉(zhuǎn)換為es5,也可以轉(zhuǎn)換JSX等語(yǔ)法。 我們?cè)陧?xiàng)目中都是通過配置插件和預(yù)設(shè)(多個(gè)插件的集合)來(lái)轉(zhuǎn)換特定代碼,例如env、stage-0等。 實(shí)際上babel可以通過自定義插件的方式實(shí)現(xiàn)任何

    babel是一個(gè)轉(zhuǎn)碼器,目前開發(fā)react、vue項(xiàng)目都要使用到它。它可以把es6+的語(yǔ)法轉(zhuǎn)換為es5,也可以轉(zhuǎn)換JSX等語(yǔ)法。

    我們?cè)陧?xiàng)目中都是通過配置插件和預(yù)設(shè)(多個(gè)插件的集合)來(lái)轉(zhuǎn)換特定代碼,例如env、stage-0等。

    實(shí)際上babel可以通過自定義插件的方式實(shí)現(xiàn)任何代碼的轉(zhuǎn)換,接下來(lái)我們通過一個(gè)“把es6的 class 轉(zhuǎn)換為es5”的例子來(lái)了解一下babel。

    內(nèi)容如下:

    webpack環(huán)境配置

    大家應(yīng)該都配置過babel-core這個(gè)loader,它的作用是提供babel的核心Api,實(shí)際上我們的代碼轉(zhuǎn)換都是通過插件來(lái)實(shí)現(xiàn)的。

    接下來(lái)我們不用第三方的插件,自己實(shí)現(xiàn)一個(gè)es6類轉(zhuǎn)換插件。先執(zhí)行以下幾步初始化一個(gè)項(xiàng)目:

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

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

    接下來(lái)我們?cè)趎ode_modules中新建一個(gè)babel-plugin-transform-class的文件夾來(lái)寫插件的邏輯(如果是真實(shí)項(xiàng)目,你需要編寫這個(gè)插件并發(fā)布到npm倉(cāng)庫(kù)),如下圖:

    紅色區(qū)域是我新建的文件夾,它上面的是一個(gè)標(biāo)準(zhǔn)的插件的項(xiàng)目結(jié)構(gòu),為了方便我只寫了核心的index.js文件。

    如何編寫bable插件

    babel插件其實(shí)是通過AST(抽象語(yǔ)法樹)實(shí)現(xiàn)的。

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

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

    好,先介紹一個(gè)工具:astexplorer.net:

    這個(gè)工具可以把一段代碼轉(zhuǎn)換為AST:

    如圖,我們寫了一個(gè)es6的類,然后網(wǎng)頁(yè)的右邊幫我們生成了一個(gè)AST,其實(shí)就是把每一行代碼變成了一個(gè)對(duì)象,這樣我們就實(shí)現(xiàn)了一個(gè)映射。

    再介紹一個(gè)文檔: babel-types :

    這是創(chuàng)建AST節(jié)點(diǎn)的api文檔。

    比如,我們想創(chuàng)建一個(gè)類,先到astexplorer.net中轉(zhuǎn)換,發(fā)現(xiàn)類對(duì)應(yīng)的AST類型是 ClassDeclaration 。好,我們?nèi)ノ臋n中搜索,發(fā)現(xiàn)調(diào)用下面的api就可以了:

    創(chuàng)建其他語(yǔ)句也是一樣的道理,有了上面這兩個(gè)東西,我們可以做任何轉(zhuǎn)換了。

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

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

    代碼中有兩個(gè)參數(shù),第一個(gè) {types:t} 東西是從參數(shù)中解構(gòu)出變量t,它其實(shí)就是babel-types文檔中的t(下圖紅框),它是用來(lái)創(chuàng)建節(jié)點(diǎn)的:

    第二個(gè)參數(shù) path ,它是捕獲到的節(jié)點(diǎn)對(duì)應(yīng)的信息,我們可以通過 path.node 獲得這個(gè)節(jié)點(diǎn)的AST,在這個(gè)基礎(chǔ)上進(jìn)行修改就能完成了我們的目標(biāo)。

    如何把es6的class轉(zhuǎn)換為es5的類

    上面都是預(yù)備工作,真正的邏輯從現(xiàn)在才開始,我們先考慮兩個(gè)問題:

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

     

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

    接下來(lái)我們開始寫代碼,思路是:

    1. 拿到老的AST節(jié)點(diǎn)
    2. 創(chuàng)建一個(gè)數(shù)組用來(lái)盛放新的AST節(jié)點(diǎn)(雖然原class只是一個(gè)節(jié)點(diǎn),但是替換后它會(huì)被若干個(gè)函數(shù)節(jié)點(diǎn)取代) 初始化默認(rèn)的 constructor 節(jié)點(diǎn)(上文提到,class中有可能沒有定義constructor)
    3. 循環(huán)老節(jié)點(diǎn)的AST對(duì)象(會(huì)循環(huán)出若干個(gè)函數(shù)節(jié)點(diǎn))
    4. 判斷函數(shù)的類型是不是 constructor ,如果是,通過取到數(shù)據(jù)創(chuàng)建一個(gè)普通函數(shù)節(jié)點(diǎn),并更新默認(rèn) constructor 節(jié)點(diǎn)
    5. 處理其余不是 constructor 的節(jié)點(diǎn),通過數(shù)據(jù)創(chuàng)建 prototype 類型的函數(shù),并放到 es5Fns
    6. 循環(huán)結(jié)束,把 constructor 節(jié)點(diǎn)也放到 es5Fns
    7. 判斷es5Fns的長(zhǎng)度是否大于1,如果大于1使用 replaceWithMultiple 這個(gè)API更新AST
    module.exports = function ({ types: t }) {
     return {
     visitor: {
     ClassDeclaration(path) {
     //拿到老的AST節(jié)點(diǎn)
     let node = path.node
     let className = node.id.name
     let classInner = node.body.body
     //創(chuàng)建一個(gè)數(shù)組用來(lái)成盛放新生成AST
     let es5Fns = []
     //初始化默認(rèn)的constructor節(jié)點(diǎn)
     let newConstructorId = t.identifier(className)
     let constructorFn = t.functionDeclaration(newConstructorId, [t.identifier('')], t.blockStatement([]), false, false)
     //循環(huán)老節(jié)點(diǎn)的AST對(duì)象
     for (let i = 0; i < classInner.length; i++) {
     let item = classInner[i]
     //判斷函數(shù)的類型是不是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的節(jié)點(diǎn)
     else {
     let protoTypeObj = t.memberExpression(t.identifier(className), t.identifier('prototype'), false)
     let left = t.memberExpression(protoTypeObj, t.identifier(item.key.name), false)
     //定義等號(hào)右邊
     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)
     }
    
     }
     //循環(huán)結(jié)束,把constructor節(jié)點(diǎn)也放到es5Fns中
     es5Fns.push(constructorFn)
     //判斷es5Fns的長(zhǎng)度是否大于1
     if (es5Fns.length > 1) {
     path.replaceWithMultiple(es5Fns)
     } else {
     path.replaceWith(constructorFn)
     }
     }
     }
     };
    }

    優(yōu)化繼承

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

    打包后代碼

     

    運(yùn)行 npm start 打包后,我們看到打包后的文件里 class

    語(yǔ)法已經(jīng)成功轉(zhuǎn)換為一個(gè)個(gè)的es5函數(shù)。

    結(jié)尾

    現(xiàn)在一個(gè)類轉(zhuǎn)換器就寫完了,希望能對(duì)大家了解babel有一點(diǎn)幫助。也希望大家多多支持腳本之家。

    聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    詳解如何用babel轉(zhuǎn)換es6的class語(yǔ)法

    詳解如何用babel轉(zhuǎn)換es6的class語(yǔ)法:babel是一個(gè)轉(zhuǎn)碼器,目前開發(fā)react、vue項(xiàng)目都要使用到它。它可以把es6+的語(yǔ)法轉(zhuǎn)換為es5,也可以轉(zhuǎn)換JSX等語(yǔ)法。 我們?cè)陧?xiàng)目中都是通過配置插件和預(yù)設(shè)(多個(gè)插件的集合)來(lái)轉(zhuǎn)換特定代碼,例如env、stage-0等。 實(shí)際上babel可以通過自定義插件的方式實(shí)現(xiàn)任何
    推薦度:
    標(biāo)簽: 轉(zhuǎn)換 如何 語(yǔ)法
    • 熱門焦點(diǎn)

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 国产麻豆一精品一AV一免费| 国产精品黄网站| 国产精品毛片VA一区二区三区| 国产精品无码免费播放| 精品无码无人网站免费视频| 久久久久国产精品麻豆AR影院 | 国产麻豆精品一区二区三区v视界| 精品久久久久久99人妻| 老司机99精品99| 精品国产v无码大片在线观看 | 国产日韩一区在线精品欧美玲| 亚洲精品无码mv在线观看网站| 国产呦小j女精品视频| 亚洲国产成人精品不卡青青草原| 精品国产v无码大片在线观看| 亚洲国产精品SSS在线观看AV| 麻豆精品国产自产在线观看一区| 国产精品igao视频| 一区二区三区国产精品| 久久国产精品久久国产精品| 国产日韩精品欧美一区喷水| 亚洲精品国精品久久99热一| 无码日韩精品一区二区人妻 | 国内揄拍高清国内精品对白| 在线精品亚洲一区二区三区| 久久久久久久久久免免费精品| 国产精品永久免费视频| www.日韩精品| 国产av无码专区亚洲国产精品| 老司机69精品成免费视频| 柠檬福利精品视频导航| 欧美777精品久久久久网| 久久精品国产一区| 女人香蕉久久**毛片精品| 四虎精品8848ys一区二区| 色花堂国产精品第一页| 91精品国产综合久久四虎久久无码一级| 日本欧美韩国日本精品| 国产成人精品久久一区二区三区av| 99久久精品费精品国产 | 91精品国产91久久久久久|