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局部)。

转换逻辑编写

  1. 我的项目里运行装置GoGoCode
npm install gogocode复制代码
  1. 初始化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);    },  },};`)复制代码
  1. 咱们要寻找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数组

  1. customKeyCodeList加上零碎的keyCode,结构全量的keyCodeMap
// 全量的keyCode对照表,基于篇幅这里只列出3个// https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent/keyCodelet 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结构后果

  1. Vue3要求: Vue.config.keyCodes不再反对,须要移除。find到这个节点,应用remove API移除
scriptAst.find(`Vue.config.keyCodes = $_$`).remove()复制代码
  1. 初始化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 } })复制代码
  1. 应用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工具查到的

  1. 最初输入,功败垂成,比照一下转换的后果

4 总结

这段代码里的AST相干操作只有10行左右,其余都是外围转换逻辑。GoGoCode能够像应用Jquery操作DOM的一样的体验来操作AST,入门简略应用也不便

starter里还有批量解决文件的demo github.com/thx/gogocod…

Github上提issues也很快就有回应! github.com/thx/gogocod…

切实是代码转换利器

如果文中有任何问题,欢迎您的反馈。

谢谢,祝你有美妙的一天!