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

資訊專欄INFORMATION COLUMN

Babylon-AST初探-實戰(zhàn)

godiscoder / 831人閱讀

摘要:生成屬性這一步,我們要先提取原函數(shù)中的的對象。所以這里我們還是主要使用來訪問節(jié)點獲取第一級的,也就是函數(shù)體將合并的寫法用生成生成生成插入到原函數(shù)下方刪除原函數(shù)程序輸出將中的屬性提升一級這里遍歷中的屬性沒有再采用,因為這里結(jié)構(gòu)是固定的。

??經(jīng)過之前的三篇文章介紹,ASTCRUD都已經(jīng)完成。下面主要通過vue轉(zhuǎn)小程序過程中需要用到的部分關(guān)鍵技術(shù)來實戰(zhàn)。

下面的例子的核心代碼依然是最簡單的一個vue示例

const babylon = require("babylon")
const t = require("@babel/types")
const generate = require("@babel/generator").default
const traverse = require("@babel/traverse").default

const code = `
export default {
  data() {
    return {
      message: "hello vue",
      count: 0
    }
  },
  methods: {
    add() {
      ++this.count
    },
    minus() {
      --this.count
    }
  }
}
`

const ast = babylon.parse(code, {
  sourceType: "module",
  plugins: ["flow"]
})

??經(jīng)過本文中的一些操作,我們將獲得最終的小程序代碼如下:

Page({
  data: (() => {
      return {
        message: "hello vue",
        count: 0
      }
  })(),
  add() {
    ++this.data.count
    this.setData({
      count: this.data.count
    })
  },
  minus() {
    --this.data.count
    this.setData({
      count: this.data.count
    })
  }
})

??注意:,跟我們之前介紹的一致,為了完成上述轉(zhuǎn)換,要把輸入和輸出均放入AST explorer,查看其先后的結(jié)構(gòu)對比。

vue代碼轉(zhuǎn)小程序

??對比文章一開始展示的兩份代碼,為了實現(xiàn)轉(zhuǎn)換,我們需要以下步驟:

data函數(shù)轉(zhuǎn)data屬性,然后刪除data函數(shù)

methods里的屬性提取出來,放到和data同一層級中,methods也要刪除

將所有的this.[data member]轉(zhuǎn)換為this.data.[data member]。注意這里只轉(zhuǎn)data中的屬性

在變更this.data的下面,插入this.setData來觸發(fā)數(shù)據(jù)變更

??下面將按照這一步驟,一步一步完成轉(zhuǎn)換,我覺得看到每一步的代碼變化還是很有成就感滴。

生成data屬性

??這一步,我們要先提取原data函數(shù)中的return的對象。結(jié)合AST explorer,可以很方便的找到這一路徑。

const dataObject = ast.program.body[0].declaration.properties[0].body.body[0].argument
console.log(dataObject)

??可是這段代碼的可讀性和魯棒性基本是0啊。它強依賴我們書寫的data函數(shù)是第一個屬性。所以這里我們還是主要使用traverse來訪問節(jié)點:

traverse(ast, {
  ObjectMethod(path) {
    if (path.node.key.name === "data") {
      // 獲取第一級的 BlockStatement,也就是data函數(shù)體
      let blockStatement = null
      path.traverse({  //將traverse合并的寫法
        BlockStatement(p) {
          blockStatement = p.node
        }
      })

      // 用blockStatement生成ArrowFunctionExpression
      const arrowFunctionExpression = t.arrowFunctionExpression([], blockStatement)
      // 生成CallExpression
      const callExpression = t.callExpression(arrowFunctionExpression, [])
      // 生成data property
      const dataProperty = t.objectProperty(t.identifier("data"), callExpression)
      // 插入到原data函數(shù)下方
      path.insertAfter(dataProperty)

      // 刪除原data函數(shù)
      path.remove()
      // console.log(arrowFunctionExpression)
    }
  }
})

console.log(generate(ast, {}, code).code)

程序輸出:

export default {
  data: (() => {
    return {
      message: "hello vue",
      count: 0
    };
  })(),
  methods: {
    add() {
      ++this.count;
    },

    minus() {
      --this.count;
    }

  }
};
methods中的屬性提升一級

??這里遍歷methods中的屬性沒有再采用traverse,因為這里結(jié)構(gòu)是固定的。

traverse(ast, {
  ObjectProperty(path) {
    if (path.node.key.name === "methods") {
      // 遍歷屬性并插入到原methods之后
      path.node.value.properties.forEach(property => {
        path.insertAfter(property)
      })
      // 刪除原methods
      path.remove()
    }
  }
})

程序輸出:

export default {
  data: (() => {
    return {
      message: "hello vue",
      count: 0
    };
  })(),

  minus() {
    --this.count;
  },

  add() {
    ++this.count;
  }

};
this.member轉(zhuǎn)為this.data.member

??這一步,首先要從data屬性中提取數(shù)據(jù)屬性。這個有些依賴data中的函數(shù)到底寫成怎么樣,如果寫成:

  data: (() => {
    const obj = {}
    obj.message = "hello vue"
    obj.count = 0
    return obj
  })(),

??這將不符合我們這里的轉(zhuǎn)化方法。當(dāng)然我們可以通過求值來獲取最終的對象,但這里也有缺陷。另一個思路是遍歷其他成員函數(shù),使用排除法。

??總之,我們需要一個方法來獲取this.data中的屬性。本文將繼續(xù)以代碼中的例子,通過data中的return方法來獲取。

// 獲取`this.data`中的屬性
const datas = []
traverse(ast, {
  ObjectProperty(path) {
    if (path.node.key.name === "data") {
      path.traverse({
        ReturnStatement(path) {
          path.traverse({
            ObjectProperty(path) {
              datas.push(path.node.key.name)
              path.skip()
            }
          })
          path.skip()
        }
      })
    }
    path.skip()
  }
})
console.log(datas)

程序輸出:

[ "message", "count" ]

??修改數(shù)據(jù)屬性至this.data.

traverse(ast, {
  MemberExpression(path) {
    if (path.node.object.type === "ThisExpression" && datas.includes(path.node.property.name)) {
      path.get("object").replaceWithSourceString("this.data")
    }
  }
})

至此程序輸出:

export default {
  data: (() => {
    return {
      message: "hello vue",
      count: 0
    };
  })(),

  minus() {
    --this.data.count;
  },

  add() {
    ++this.data.count;
  }

};
添加this.setData方法

??要想在變更this.data的下面,插入this.setData,我們首先要找到它插入的位置,即this.data的父節(jié)點,所以這就是我們的第一步操作:(MemberExpression就是上一步的,因為這一步的path與上一步相同)

traverse(ast, {
  MemberExpression(path) {
    if (path.node.object.type === "ThisExpression" && datas.includes(path.node.property.name)) {
      path.get("object").replaceWithSourceString("this.data")
    }
  }
  const expressionStatement = path.findParent((parent) =>   
    parent.isExpressionStatement()
  )
})

??找到插入的位置后,我們就要構(gòu)造要插入的函數(shù),這時就用到了我們在這個系列第一篇文章中介紹的(Create)[https://summerrouxin.github.i...]操作,忘記的可以去復(fù)習(xí)下哦,下面我們直接上代碼,大家看這段代碼一定要對照AST explorerh和babel-typesAPI,然后找到從外向內(nèi)一層一層的對照。這段代碼的邏輯大概如下:

找到要插入的代碼的位置,首先要判斷是不是賦值操作,如果是的話找到this.member的父結(jié)點

新建要插入的結(jié)點

插入節(jié)點

traverse(ast, {
  MemberExpression(path) {
    if (path.node.object.type === "ThisExpression" && datas.includes(path.node.property.name)) {
      path.get("object").replaceWithSourceString("this.data")
      //一定要判斷一下是不是賦值操作
      if(
        (t.isAssignmentExpression(path.parentPath) && path.parentPath.get("left") === path) ||
        t.isUpdateExpression(path.parentPath)
      ) {
          // findParent
          const expressionStatement = path.findParent((parent) =>   
            parent.isExpressionStatement()
          )
          // create
          if(expressionStatement) {
            const finalExpStatement =
              t.expressionStatement(
                t.callExpression(
                  t.memberExpression(t.thisExpression(), t.identifier("setData")),
                  [t.objectExpression([t.objectProperty(
                    t.identifier(propertyName), t.identifier(`this.data.${propertyName}`)
                  )])]
                )
              )
            expressionStatement.insertAfter(finalExpStatement)
          }  
      }
    }
  }
})

程序輸出:

export default {
  data: (() => {
    return {
      message: "hello vue",
      count: 0
    };
  })(),

  minus() {
    --this.count;
    this.setData({
      count: this.data.count
    })
  },

  add() {
    ++this.count;
    this.setData({
      count: this.data.count
    })
  }

};

??以上就是我們實戰(zhàn)介紹,這邊只涉及到vue轉(zhuǎn)小程序的部分代碼,以后可以考慮繼續(xù)介紹其他模塊。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/107867.html

相關(guān)文章

  • Babylon-AST初探-代碼更新&刪除(Update & Remove)

    摘要:操作通常配合來完成。因為是個數(shù)組,因此,我們可以直接使用數(shù)組操作自我毀滅方法極為簡單,找到要刪除的,執(zhí)行就結(jié)束了。如上述代碼,我們要刪除屬性,代碼如下到目前為止,的我們都介紹完了,下面一篇文章以轉(zhuǎn)小程序為例,我們來實戰(zhàn)一波。 ??通過前兩篇文章的介紹,大家已經(jīng)了解了Create和Retrieve,我們接著介紹Update和 Remove操作。Update操作通常配合Create來完成。...

    levius 評論0 收藏0
  • Babylon-AST初探-代碼查詢(Retrieve)

    摘要:針對語法樹節(jié)點的查詢操作通常伴隨著和這兩種方法見下一篇文章。注意上述代碼打印出的和中的并不完全一致。如函數(shù),在中的為,但其實際的為。這個大家一定要注意哦,因為在我們后面的實際代碼中也有用到。 ??在上一篇文章中,我們介紹了AST的Create。在這篇文章中,我們接著來介紹AST的Retrieve。??針對語法樹節(jié)點的查詢(Retrieve)操作通常伴隨著Update和Remove(這兩...

    wangdai 評論0 收藏0
  • Netty4.x 源碼實戰(zhàn)系列(一):ServerBootstrap 與 Bootstrap 初探

    摘要:而用于主線程池的屬性都定義在中本篇只是簡單介紹了一下引導(dǎo)類的配置屬性,下一篇我將詳細(xì)介紹服務(wù)端引導(dǎo)類的過程分析。 從Java1.4開始, Java引入了non-blocking IO,簡稱NIO。NIO與傳統(tǒng)socket最大的不同就是引入了Channel和多路復(fù)用selector的概念。傳統(tǒng)的socket是基于stream的,它是單向的,有InputStream表示read和Outpu...

    BakerJ 評論0 收藏0
  • 云智慧壓測實戰(zhàn)分享之JMeter工具使用初探

    摘要:有了測試腳本,通過線程組來模擬真實用戶對服務(wù)器的訪問壓力。不同的是,這些類型的線程執(zhí)行測試結(jié)束后執(zhí)行定期的線程組。線程組中包含的線程數(shù)量在測試執(zhí)行過程中是不會發(fā)生改變的。邏輯控制器元件只對其子節(jié)點中的取樣器和邏輯控制器作用。 工欲善其事必先利其器,要保證移動應(yīng)用產(chǎn)品在上線之后能穩(wěn)定運行于各種復(fù)雜環(huán)境,僅僅進行功能測試是遠(yuǎn)遠(yuǎn)不夠的,壓力測試越來越被應(yīng)用開發(fā)商所重視。而壓力測試從傳統(tǒng)的內(nèi)部...

    venmos 評論0 收藏0

發(fā)表評論

0條評論

godiscoder

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<