Vue 自定义组件库问题记录

qb-ui是我自己开发的一个 Vue 组件库,包含了一些常用的基础组件,目前处于开发的初级阶段。
本文旨在记录开发过程中遇到的一些问题以及我采取的解决方案。

组件 CSS 作用域

对于一个组件,我们希望它的 CSS 只作用于当前组件内的元素,所以我们平时在写项目时会给每个组件的 Vue 单页面文件的 style 标签加上了 scoped 属性。编译后,HTML 标签会被自动添加一个随机生成的唯一属性 (比如 data-v-f3f3eg9) ,同时对应的 CSS 选择器也会增加同名的属性选择器(如。example[data-v-f3f3eg9]),这样组件内的 CSS 便指定了作用域。

通过 scoped 属性的确能达到给组件样式设置作用域的目的,基本能避免组件内的样式影响外部,但是它也带来了另外一个问题:外部覆盖内部样式不方便。无论组件功能多么通用,接口多么灵活,只要涉及到 UI,就难免无法满足所有项目样式需求,所以应该允许在具体的项目中根据需要覆盖组件部分甚至全部样式。而 scoped 随机生成属性名提高了覆盖样式的难度。

我在开发qb-ui的时候 css 预处理使用的 scss,参考了几大常用的组件库后,最后在组件里移除了 scoped 属性,改用 class 策略来避免组件内样式影响外部,也就是把theme作为一个模块对待。在theme-default文件夹下使用 gulp 把 scss 转化成 css 导出到 lib 文件夹,然后把 lib 文件夹像其他模块一样引入到 index.js 。

注意,使用 class 策略时要注意 css 命名规范,这里我采用的是 BEM 规范

当然,scoped 属性也不是没有存在的意义,它更适合在具体应用中使用,对于复用性高的组件来说,不是最佳选择。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
C:\code\Vue\vue-UI\qb-ui\packages
├─index.js
├─theme-default
| ├─.gitignore
| ├─gulpfile.js
| ├─package-lock.json
| ├─package.json
| ├─src
| | ├─base.scss
| | ├─button.scss
| | ├─col.scss
| | ├─icon.scss
| | ├─index.scss
| | ├─reset.scss
| | ├─row.scss
| | ├─tag.scss
| | ├─mixins
| | ├─fonts
| | ├─common
| ├─lib
├─tag
| ├─index.js
| ├─src
| | └main.vue
├─row
| ├─index.js
| ├─src
| | └row.js
├─icon
| ├─index.js
| ├─src
| | └main.vue
├─col
| ├─index.js
| ├─src
| | └col.js
├─button-group
| ├─index.js
| ├─src
| | └main.vue
├─button
| ├─index.js
| ├─src
| | └main.vue