Closed yuxino closed 3 years ago
我们可以看见Vue Loader里面有两种处理样式的方案。一种是Scoped CSS还有一种是CSS Modules。下面来做一些优缺点对比。
Scoped CSS
CSS Modules
开箱即用。能避免样式冲突(但是不完全)。
引用包含scoped的第三方插件时如若需要修改样式则需要全局修改,而且要注意权重问题,迫不得已再使用!important。
如果样式和全局的样式重名,依然会导致样式冲突。
Scoped 样式不能代替 class。考虑到浏览器渲染各种 CSS 选择器的方式,当 p { color: red } 是 scoped 时 (即与特性选择器组合使用时) 会慢很多倍。 如果你使用 class 或者 id 取而代之,比如 .example { color: red },性能影响就会消除。
p { color: red }
.example { color: red }
这句话的意思是可能有人会觉得有了Scoped就可以直接不写class或者id了。直接给标签写样式。虽然可以但是效率会很低,因为用到了特性选择器。
Scoped
class
id
特性选择器
举个例子:
在递归组件中小心使用后代选择器! 对选择器 .a .b 中的 CSS 规则来说,如果匹配 .a 的元素包含一个递归子组件,则所有的子组件中的 .b 都将被这个规则匹配。
Google 资深web开发工程师 Steve Souders 对 CSS 选择器的执行效率从高到低做了一个排序:
如何减少 CSS 选择器性能损耗? Google 资深web开发工程师 Steve Souders 对 CSS 选择器的执行效率从高到低做了一个排序:
1.id选择器(#myid) 2.类选择器(.myclassname) 3.标签选择器(div,h1,p) 4.相邻选择器(h1+p) 5.子选择器(ul < li) 6.后代选择器(li a) 7.通配符选择器(*) 8.属性选择器(a[rel="external"]) 9.伪类选择器(a:hover, li:nth-child)
根据以上「选择器匹配」与「选择器执行效率」原则,我们可以通过避免不恰当的使用,提升 CSS 选择器性能。
名字会有postcss生成转成hash。
因为名字转成hash了,选择器也没有必要了。
可以在.vue文件写很多个style,但是正常人会这样吗?
.vue
<style module="a"> /* 注入标识符 a */ </style> <style module="b"> /* 注入标识符 b */ </style>
<script> export default { created () { console.log(this.$style.red) // -> "red_1VyoJ-uZ" // 一个基于文件名和类名生成的标识符 } } </script>
可以组合其他的样式。
.className { color: green; background: red; } .otherClassName { composes: className; color: yellow; }
composes可以写很多条。但是必须得写在其他CSS规则之前。
需要手动配置在webpack加css-loader并传入modules:true。
css-loader
modules:true
// webpack.config.js { module: { rules: [ // ... 其它规则省略 { test: /\.css$/, use: [ 'vue-style-loader', { loader: 'css-loader', options: { // 开启 CSS Modules modules: true, // 自定义生成的类名 localIdentName: '[local]_[hash:base64:8]' } } ] } ] } }
然后才可以使用
<style module> .red { color: red; } .bold { font-weight: bold; } </style>
由于Scoped CSS在CSS Modules之前就出现了,会有更多的解决方案和项目用到。找资料的时候比较方便,CSS Modules是比较后面出来的,写法也不一样,需要一点点的学习成本。
其实这个也还好,因为样式名是动态生成的,可以理解。和以前直接写class还是有区别的。最糟糕的可能是混着写,因为不免会用到一些三方的CSS。可能在一个组件里会有部分是:class部分直接写的class。
:class
使用CSS modules处理动画animation的关键帧keyframes,动画名称必须先写。
animation: ani 1s;能正常编译,而animation: 1s ani;则会编译的不符合预期,所以平时养成良好的css参数书写顺序也很重要。
nimation: ani 1s;
animation: 1s ani;
使用module的父组件会在没有使用module的子组件的所有根类上增加hash改变其类名,可能会造成子组件样式应用不上。
如下是没有开启css module子组件的样式:
<style lang="scss"> .comp{ color: palegoldenrod; p{ color: black; } } .t { color: teal; } div { color: yellow; } </style>
父组件开启css module后编译结果如下:
.comp_2tR6GNan { color: palegoldenrod; } .comp_2tR6GNan p { color: black; } .t_39GmF73s { color: teal; } div { color: yellow; }
可以看到comp和t类都被修改了类名,如果根样式是标签选择器不会受影响。
所以在使用css module的父组件中使用的子组件也要开启css module。
总的来看CSS Modules的坑会少一点。所以选型上我会比较偏向CSS Modules。
老哥 第一句话. ~Spoced CSS~ => Scoped CSS
Spoced CSS
@LonelyLiaR ok
覆盖第三方利用了scoped的插件,一般使用的还是穿透属性吧
我们可以看见Vue Loader里面有两种处理样式的方案。一种是
Scoped CSS
还有一种是CSS Modules
。下面来做一些优缺点对比。Scoped CSS的优点
开箱即用。能避免样式冲突(但是不完全)。
Scoped CSS的缺点
覆盖第三方利用了scoped的插件
引用包含scoped的第三方插件时如若需要修改样式则需要全局修改,而且要注意权重问题,迫不得已再使用!important。
冲突
如果样式和全局的样式重名,依然会导致样式冲突。
需要注意的问题
这句话的意思是可能有人会觉得有了
Scoped
就可以直接不写class
或者id
了。直接给标签写样式。虽然可以但是效率会很低,因为用到了特性选择器
。举个例子:
在递归组件中小心使用后代选择器! 对选择器 .a .b 中的 CSS 规则来说,如果匹配 .a 的元素包含一个递归子组件,则所有的子组件中的 .b 都将被这个规则匹配。
选择器性能问题
Google 资深web开发工程师 Steve Souders 对 CSS 选择器的执行效率从高到低做了一个排序:
根据以上「选择器匹配」与「选择器执行效率」原则,我们可以通过避免不恰当的使用,提升 CSS 选择器性能。
CSS Modules 优点
不冲突
名字会有postcss生成转成hash。
性能更好一点
因为名字转成hash了,选择器也没有必要了。
多style
可以在
.vue
文件写很多个style,但是正常人会这样吗?可以通过js直接访问样式名
Composition
可以组合其他的样式。
composes可以写很多条。但是必须得写在其他CSS规则之前。
CSS Modules的缺点
并非开箱即用
需要手动配置在webpack加
css-loader
并传入modules:true
。然后才可以使用
新的写法
由于Scoped CSS在CSS Modules之前就出现了,会有更多的解决方案和项目用到。找资料的时候比较方便,CSS Modules是比较后面出来的,写法也不一样,需要一点点的学习成本。
必须使用:class
其实这个也还好,因为样式名是动态生成的,可以理解。和以前直接写class还是有区别的。最糟糕的可能是混着写,因为不免会用到一些三方的CSS。可能在一个组件里会有部分是
:class
部分直接写的class
。使用css module在keyframes中的问题
使用CSS modules处理动画animation的关键帧keyframes,动画名称必须先写。
a
nimation: ani 1s;
能正常编译,而animation: 1s ani;
则会编译的不符合预期,所以平时养成良好的css参数书写顺序也很重要。css module父子组件问题
使用module的父组件会在没有使用module的子组件的所有根类上增加hash改变其类名,可能会造成子组件样式应用不上。
如下是没有开启css module子组件的样式:
父组件开启css module后编译结果如下:
可以看到comp和t类都被修改了类名,如果根样式是标签选择器不会受影响。
所以在使用css module的父组件中使用的子组件也要开启css module。
总结
总的来看CSS Modules的坑会少一点。所以选型上我会比较偏向CSS Modules。
相关资料