CSS的痛点
我们都知道,CSS入门简单,深入就比较难,样式简单维护难。CSS痛点也很多
1、CSS 的规则是全局的,任何一个组件的样式规则,都对整个页面有效。相信写css的人都会遇到样式冲突(污染)的问题。
2、为了解决全局污染的问题,那就把class命名写长一点吧、加一层父级选择器、降低冲突的几率,那么CSS命名混乱了
3、组件依赖管理不彻底,组件应该相互独立,引入一个组件时,应该只引入它所需要的 CSS 样式。
4、代码难以复用,出现了sass less 之类的工具
CSS模块化方案分类
1、命名约定
规范化CSS的解决方案如:BEM、OOCSS、AMCSS、SMACSS
(详情参阅https://blog.csdn.net/wulala_hei/article/details/84633258)
2、CSS in JS
彻底抛弃 CSS,用 JavaScript 写 CSS 规则,styled-components 就是其中代表。
基本用法:
import styled from 'styled-components'; const Wrapper = styled.div` /* 应用于Wrapper组件本身和Wrapper组件里的所有html标签 */ color: black; /* 应用于Wrapper组件里的h3标签 */ h3 { color: red } /* 应用于Wrapper组件里的className为blue的html标签 */ .blue { color: blue } ` render( <Wrapper> <p>黑色 p 标签 p> <h3>红色 h3 标签h3> <p className="blue" >蓝色 p 标签p> Wrapper> )
3、使用JS 来管理样式模块
使用JS编译原生的CSS文件,使其具备模块化的能力,代表是 CSS Modules。
但是这些模块化方案都是各有优缺点,如命名约定:命名复杂、CSS in JS:缺乏扩展、 CSS Modules当然也有一些缺点(你得先学会它再去谈优劣)。在众多解决方案中,没有绝对的优劣。还是要结合自己的场景来决定。
启用 CSS Modules
CSS Modules 很容易学。通过webpack 配置 css-loader
,css-loader
自带了 CSS Modules。
rules: [ { test: /\.less?$/, exclude: /node_modules/, // 排除 node_modules 文件夹 use: [MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { modules: true, } }, 'less-loader'] },]
less文件
// index.less.test{ color: skyblue;}
// index.jsximport styled from './index.less';console.log(styled); // {test: "_3XTBA4n3nuO1MaQiFTZLIV"}
如果从百度上查看关于css-loader的用法, 会发现很多关于localIdentName的使用
localIdentName是用来指定生成class的格式,localIdentName的默认值
是[hash:base64]。
但是,该参数已经被css-loader 弃用了, 如果你使用了新版的css-loader,会发现你的控制套报错。
去css-loader 的npm库中可以得知现有的options的参数:
那么新的写法是什么呢?
module.exports = { module: { rules: [ { test: /\.css$/i, loader: 'css-loader', options: { modules: { mode: 'local', localIdentName: '[path][name]__[local]--[hash:base64:5]', context: path.resolve(__dirname, 'src'), hashPrefix: 'my-custom-hash', }, }, }, ], },};
新版的css-loader将 localIdentName 属性划分给了 modules!
此时, 名为“test”的class就变成变成这样:
前端技术变化的太快了,所以才会经常发现,百度的文章在实践中并不合理,走不通
Vue scoped
实现原理:
通过观察DOM结构可以发现:vue通过在DOM结构以及css样式上加上唯一的标记,保证唯一,达到样式私有化,不污染全局的作用,如图,样式属性上也会多一个该字符,以保证唯一
可以看出加上scoped
后的组件里的标签都会多一个data-v-xxxxx
的属性,并且在css样式部分可以看出
由此可知,添加scoped
属性的组件,为了达到不污染全局,做了如下处理:
给HTML的DOM节点加一个不重复属性
data-v-xxxxxx
标志唯一性在添加
scoped
属性的组件的每个样式选择器后添加一个等同与“不重复属性”相同的字段,实现类似于“作用域”的作用,不影响全局如果组件内部还有组件,只会给最外层的组件里的标签加上唯一属性字段,不影响组件内部引用的组件( 注意 )