正则重构slot指令

1,268 阅读3分钟

「这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战」。

最近想要迁移Vue2的项目到Vue3,迁移过程中发现原有代码里使用了很多 slot指令例如slot = 'xxx' 跟 slot-scope = ’xxx'  直接在组件上的旧写法,每迁移一个页面就有很多类似的代码要重构不改的话会报错,原因是在2.6.0版本slot跟slot-scope写法已经过时,新出v-slot指令替代,与v-bind v-on 等类似可用语法糖#,slot跟slot-scope的旧写法上到Vue3 则彻底不可用。

因为项目版本 为 2.6.+, 可以使用v-slot指令,而且搜了一下项目有上千个slot跟slot-scope。 所以决定抽空全局重构,为后续迁移节省一点成本。下面介绍一下v-slot指令以及重构思路步骤。

v-slot

熟悉模板引擎语言例如Jinja的同学都知道,slot是插槽的意思、在模板中预留一块区域,可以被具体实现模板的页面重新实现、替换。

在Vue中插槽可作为子组件的预留区域,父组件中实现的插槽可以访问当子组件预留区域的变量,slot跟slot-scope写法不赘述,感兴趣可以翻阅官方文档。

而对于v-slot 指令,有如下几条规则:

  1. v-slot 不能用在HTML标签上,如 div span p等标签,只能用在template或者组件上,否则vue会报错;

  2. 当v-slot用在组件上的时候,组件内又有一个<template v-slot>,这样的话Vue也会报错因为scope不明确,例如

    <component #slotProps>	
        <template v-slot:child></template>
    </component>
    
  3. v-slot 跟 旧的 slot 跟 slot-scope语法一起用时,Vue还会报错因为旧的语法在Vue3中被废弃了;

  4. <template v-slot> 不能作为HTML 的子节点;

  5. 多个v-slot的话,只有第一个有效,其余的被忽略。

重构

下面介绍一下重构的思路,本来想用jscodeshift,用脚本重构可能效率跟精准度都比较好,奈何学艺不精,对jscodeshift的掌握程度不够,所以决定用正则去替换将例如<div slot="xxx"></div> 的代码替换成为 <template #xxx><div></div></template>

步骤拆解为:

  1. 识别到 对应的标签;

  2. 加上template v-slot标签;

  3. 去除掉原有的slot标签。

具体实施为:

  1. 打开vscode的全局搜索;

  2. 由于项目里基本都是几种组件具有slot属性所以对每个分批进行处理 :
    <xxx.?slot="(.?)".?\/?>[\n]+([\s\S])?<\/xxx>=> <temlate #$1>$0</template>

  3. <xxx (slot=".?")(.?)> =><xxx $2>

  4. 对于每个比如div,span组件进行以上重复操作;

  5. <template slot-scope> 则类似第三步统一替换。

以上是用正则重构slot标签的思路跟具体步骤,结果则不方便截图了。用时大约两个小时,因为一边调试一边确保替换后的结果是可以运行的,vscode还有个坑,当一个文件有两个及以上含slot的tag时点全部替换(ctrl+shift+enter),第二个及以后都会被替换成第一个slot的值,可能是写入的结果不能及时同步导致的,所以对于两个及以上slot的文件需要单独处理,即一个一个点击替换(ctrl+shift+1)。总结是对于有规则的替换可以合理使用正则跟脚本,减少重复操作带来的枯燥感。如有更高效的重构方法,欢迎评论区留言。

感谢阅读

Happy coding

参考

v-slot directive should be used properly

Slots