某次小组内开周会,提到开发效率的问题,有个小伙伴提到写新页面的时候,template
大概布局写完后,对着 template
结构写 scss
是件比较耗时耗力的事情,如果能作出一个自动依据 template
结构生成 scss
文件的 vscode
插件就好了
我当时也没在意,后来周会结束后觉得这事情可以做一下,于是抽空看了下 vscode
扩展的开发文档,就上手 code
了,做出来后效果还不错,最起码不用再做人工对着 template
写 scss
这种没技术含量的事情了,写好了一大堆 template
之后,一键转换,还是挺爽的
插件已经发布到 vscode
扩展市场,可以在vscode
插件市场查找安装,或者 vscode
上直接搜索 AutoScssStruct4Vue 安装
插件的源码已经上传到 Github ,需要的可自取,如果有问题,直接提 issue 即可
模板解析
scss
文件的关键就是选择器,能在模板上体现出来的选择器属性有 class
、id
和标签名,所以必须要从模板中取得所有的选择器
模板的处理实际上就是字符串的处理,通过正则表达式从 <template>...</template>
中提取所需的选择器名,既然是 vue
,我第一个就想到直接从 vue
源码中将 vue
处理 template
的部分抄过来,不过后来看了一下源码,想法可行,但是性价比不高
vue
将 template
解析成 ast
的部分,与其他的一些处理逻辑耦合在一起了,而且处理了很多我并不需要的东西,比如指令、组件这些,我只是想取个选择器属性而已,所以这个想法就放弃了
再仔细一想,抛开 vue
的那些东西来看(比如指令处理这些),其实处理 template
跟处理普通的 html
片段没太大区别,于是问题就变成了将html
片段转为 ast
,这个就容易很多了
不过还是有些差别,毕竟 vue
的 template
和普通 html
片段之间的处理方式还是有点不同的,差异点在于 vue
的一些特性,例如 v-bind
语法,以及组件标签
v-bind
以下以 class
这个选择器属性为例,id
同此
因为考虑到 v-bind
语法,所以在 parse
模板时,正则表达式需要将这个考虑进去,属性匹配正则为:
const attrRE = /((:|v-bind:)?[\w$\-]+)|(?<word>["'"]){1}[\s\S]*?\k<word>/g;
这个正则会将标签的属性全都匹配,因为vue
的class
属性有三种写法:
- 字符串
- 数组
- 对象
所以转换为 ast
后,可能的结构有:
{
attrs: {
class: 'box1 box2'
},
bindAttrs: {
class: "['box1', name]"
}