1 为什么要迁徙 Vue3.x
说点什么呢?总之。。。这不是我的错!
首先先要写个案例,找到一个可执行计划。
2 计划抉择
参考 Vue2 转 3 官网文档
v3.cn.vuejs.org/guide/migra…
面对本人我的项目百八十个文件,人工爆肝必定是不可能的,想都不能想!惟一的计划是基于 AST(形象语法树)解构代码,依据 Vue 官网给出降级文档的批改倡议,批量批改输入文件的计划。只是。。。AST 操作有点简单。
调研了几个工具,GitHub 上找到了几个去掉代码文件里 console.log 的示例学习学习:(这两处代码援用作比照计划,能够跳过)一. 利用 jscodeshift 操作 AST 去掉 console.log 的示例:
export default (fileInfo, api) => {
const j = api.jscodeshift;
const root = j(fileInfo.source)
const callExpressions = root.find(j.CallExpression, {
callee: {
type: 'MemberExpression',
object: {type: 'Identifier', name: 'console'},
},
}
);
callExpressions.remove();
return root.toSource();};
复制代码
二. 利用 babel 操作 AST 去掉 console.log 的示例:(基于篇幅省略了局部代码,有趣味的同学请拜访 github.com/mattphillip…)
export default function({types,}: typeof BabelCore): PluginObj<ConsoleTransformState> {
return {
name: 'console-transform',
visitor: {CallExpression(path, { opts, file}) {validateSchema(schema, opts);
const {env, removeMethods, additionalStyleMethods} = opts;
const callee = path.get('callee');
/*
基于篇幅限度
此处省略 40+ 行代码
*/
},
},
};
}
复制代码
基于自己实力,这两个计划切实是劝退案例。
正在我为这个我的项目重构发愁,发量迅速缩小,混迹于社区寻找拯救计划的时候,突然发现了 GoGoCode 这个工具。
贴一段官网介绍:
GoGoCode 是一个操作 AST 的工具,能够升高应用 AST 的门槛,帮忙开发者从繁琐的 AST 操作中解放出来,更专一于代码剖析转换逻辑的开发。简略的替换甚至不必学习 AST,而初步学习了 AST 节点构造(可参考 AST 查看器)后就能够实现更简单的剖析转换。
GoGoCode 的官网文档 gogocode.io/zh/docs/spe…
这不正是我想要的么,遇到你就是古话说的,瞌睡来了有人递枕头!而 GoGoCode 操作 AST 去掉 代码中 console.log,仅仅只须要一行代码!!
$(` 要转换的代码段 `).find(`console.log($_$)`).remove()
复制代码
相熟的 $ 符号,相熟的 find、remove 等 API,扣一下题,说零老本操作 AST 不算题目党吧 爆赞!!!计划选定!!!
3 动工
举个栗子:按键修饰符的迁徙计划
Vue2 转 3 官网文档 – 按键修饰符的迁徙 v3.cn.vuejs.org/guide/migra…
以下是变更的简要总结:
- 非兼容:不再反对应用数字 (即键码) 作为 v -on 修饰符
- 非兼容:不再反对 config.keyCodes
依照文档写一个待转化的 Demo
<template>
<div>
<h1> 迁徙:按键修饰符 </h1>
<p> 迁徙策略:1.Vue3 不再反对应用数字 (即键码) 作为 v-on 修饰符
2. 不再反对 config.keyCodes</p>
<div class="mt20 text-left">
<div>space:<input type="text" @keyup.space="keys('space')" /></div>
<div>space:<input type="text" @keyup.32="keys('keycode 32 space')" /> </div>
<div>space:<input type="text" @keyup.customSpace="keys('keycode 32 space')" /> </div>
</div>
</div>
</template>
<script>
import Vue from 'vue';
Vue.config.keyCodes = {
customSpace: 32,
customDelete: 46
};
export default {
name: '按键修饰符',
methods: {keys(key) {alert('您按下的是' + key);
},
},
};
</script>
复制代码
工作确定
依据 astexplorer.net 剖析下要转换的内容
安利一下 astexplorer.net 这个工具,咱们能够利用它很不便的查看某段代码的 AST 语法树结构
这里要做的有三件事:
1)提取代码里自定义的 keyCodes(上图蓝框 Vue.config.keyCodes 的内容局部),与零碎 keyCodes 合并为一个 map,后续要在 template 替换时应用;
2)移除 Vue.config.keyCodes 代码(Vue3 不再反对);
3)遍历所有标签以及它的属性,应用合并后的 keyCodes 替换标签(上图红框 xx.32 与 xx.customSpace 局部)。
转换逻辑编写
- 我的项目里运行装置 GoGoCode
npm install gogocode
复制代码
- 初始化 script 的 AST 对象
const $ = require('gogocode');
//script 代码, 用 $ 转为 AST 节点
let scriptAst = $(`
import Vue from 'vue';
Vue.config.keyCodes = {
customSpace: 32,
customDelete: 46
};
export default {
name: '按键修饰符',
methods: {keys(key) {alert('您按下的是' + key);
},
},
};`)
复制代码
- 咱们要寻找 script 里自定义的 keyCodes(Vue.config.keyCodes 的内容局部)
应用 GoGoCode 的 find API,加上匹配通配符_,拿到所有的自定义 keyCode 数组
// 匹配取出自定义的 keyCode,后果:Node 数组
const customKeyCodeList = scriptAst.find(`Vue.config.keyCodes = {$_$}`).match[0]
复制代码
这里要留神结构匹配的 Vue.config.keyCodes = {$_$} 的字符串,须要合乎可转 AST 节点的标准 能够拿到 astexplorer.net 工具中验证一下
控制台打出 customKeyCodeList,是一个 Node 数组
- customKeyCodeList 加上零碎的 keyCode,结构全量的 keyCodeMap
// 全量的 keyCode 对照表, 基于篇幅这里只列出 3 个
// https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent/keyCode
let keyCodeMap = {46: 'delete',32: 'space',112: 'f1'}
// 加上自定义 keyCode 结构汇总所有的 keyCodeMap, 待会替换 template 内容的时候须要应用
// 后果:{46: 'delete',32: 'space',112: 'f1', customSpace: 'space', customDelete: 'delete'}
for(let i = 0;i< customKeyCodeList.length; i=i+2){
Object.assign(keyCodeMap, {[customKeyCodeList[i].value] : keyCodeMap[customKeyCodeList[i+1].value]
})
}
复制代码
控制台打出 keyCodeMap 结构后果
- Vue3 要求: Vue.config.keyCodes 不再反对, 须要移除。find 到这个节点,应用 remove API 移除
scriptAst.find(`Vue.config.keyCodes = $_$`).remove()
复制代码
- 初始化 template 节点,html 模板须要带 {parseOptions: { html: true} } 参数
let templateAst = $(`<template>
<div>
<p> 迁徙:按键修饰符 </p>
<p> 迁徙策略:1.Vue3 不再反对应用数字 (即键码) 作为 v-on 修饰符
2. 不再反对 config.keyCodes</p>
<div class="mt20 text-left">
<div>space:<input type="text" @keyup.space="keys('space')" /></div>
<div>space:<input type="text" @keyup.32="keys('keycode 32 space')" /> </div>
<div>space:<input type="text" @keyup.customSpace="keys('keycode 32 space')" /> </div>
</div>
</div>
</template>`, {parseOptions: { html: true} })
复制代码
- 应用 find、each、attr API 遍历所有的标签以及它的属性,应用 keyCodeMap,替换属性名称
//find+each 遍历所有的标签项
templateAst.find(['<$_$></$_$>', '<$_$ />']).each((node) => {
// 如果节点含有属性, 则遍历它的属性
if (Array.isArray(node.attr('content.attributes'))) {node.attr('content.attributes').forEach((attr) => {
// 应用上文结构进去的汇总 keyCodeMap, 替换匹配到的属性名 如 @keyup.32 -> @keyup.space
for (let keyItem in keyCodeMap) {if (attr.key.content.endsWith(`.${keyItem}`)) {attr.key.content = attr.key.content.replace(`.${keyItem}`,`.${keyCodeMap[keyItem]}`)
}
}
})
}
})
复制代码
这里用到的 node.attr(‘content.attributes’),就是方才从 astexplorer.net 工具查到的
- 最初输入,功败垂成,比照一下转换的后果
4 总结
这段代码里的 AST 相干操作只有 10 行左右,其余都是外围转换逻辑。GoGoCode 能够像应用 Jquery 操作 DOM 的一样的体验来操作 AST,入门简略应用也不便
starter 里还有批量解决文件的 demo github.com/thx/gogocod…
Github 上提 issues 也很快就有回应!github.com/thx/gogocod…
切实是代码转换利器
如果文中有任何问题,欢迎您的反馈。
谢谢,祝你有美妙的一天!