??通過前兩篇文章的介紹,大家已經了解了Create
和Retrieve
,我們接著介紹Update
和 Remove
操作。Update
操作通常配合Create
來完成。我們這篇文章主要介紹幾個常用的NodePath
`API:
replace、
insert、
remove`。具體也可以看babel-handbook中的Manipulation章節。
replaceWith 使用新的節點進行替換
將加法運算替換成乘法
const code = `const c = a + b`
const ast = babylon.parse(code)traverse(ast, {BinaryExpression(path) {// 注意這里要有判斷,否則會無限進入`BinaryExpression`// https://stackoverflow.com/questions/37539432/babel-maximum-call-stack-size-exceeded-while-using-path-replacewithif (path.node.operator === '+') {path.replaceWith(t.binaryExpression('*', path.node.left, path.node.right))}}
})console.log(generate(ast, {}, code).code) // const c = a * b;
將this.count
替換為this.data.count
??轉換前后的AST
展示如下圖:
??我們需要做的是,找到符合this.count
的ThisExpression
,然后把它替換為this.data
const code = `this.count`
const ast = babylon.parse(code)traverse(ast, {MemberExpression(path) {if (t.isThisExpression(path.node.object) &&t.isIdentifier(path.node.property, {name: 'count'})) {path.get('object') // 獲取`ThisExpresssion`.replaceWith(t.memberExpression(t.thisExpression(), t.identifier('data')))}}
})
console.log(generate(ast, {}, code).code) // this.data.count;
replaceWithSourceString 直接使用代碼替換
??上個例子中將this.count
替換為this.data.count
的部分,通過t.memberExpression
可以構造node
。更簡單的操作可以直接使用replaceWithSourceString
,個人覺得這個API
很好用。
path.get('object').replaceWithSourceString('this.data')
插入操作
??插入是樹操作的一種常見操作。子節點是個Array
,前、中、后各種位置都可以插入新節點。下面來介紹下pushContainer
、unshiftContainer
、insertBefore
、insertAfter
操作。
??這里以給obj
對象新增一個屬性myprop: 'hello my property'
為例:
const code = `
const obj = {count: 0,message: 'hello world'
}
`
const ast = babylon.parse(code)const property = t.objectProperty(t.identifier('myprop'),t.stringLiteral('hello my property')
)
pushContainer 父節點的操作
??父節點為子節點Array
插入一個node
traverse(ast, {ObjectExpression(path) {path.pushContainer('properties', property)}
})
insertAfter 兄弟節點的操作
??insertAfter
也可以完成上述操作,需要找到message
屬性,然后在后面插入node
就搞定啦
traverse(ast, {ObjectProperty(path) {if (t.isIdentifier(path.node.key, {name: 'message'})) {path.insertAfter(property)}}
})
??unshiftContainer
和insertBefore
與上面兩個相對應,這里不再舉例了,大家可以自己試一試。
??因為properties
是個數組,因此,我們可以直接使用數組操作
traverse(ast, {ObjectExpression(path) {// path.pushContainer('properties', property)path.node.properties.push(property)}
})
Remove 自我毀滅
??Remove
方法極為簡單,找到要刪除的NodePath
,執行Remove
就結束了。如上述代碼,我們要刪除message
屬性,代碼如下:
traverse(ast, {ObjectProperty(path) {if (t.isIdentifier(path.node.key, {name: 'message'})) {path.remove()}}
})
到目前為止,AST的CURD
我們都介紹完了,下面一篇文章以vue
轉小程序
為例,我們來實戰一波。