文档更新时版本为 v1.4.3
webpack的自定义loader模块,给html文件中标签加入自定义属性以起到隔离作用域的作用,依赖于 css-attr-scope-loader
css-attr-scope-loader 模块参考:http://github.com/xuxusheng/css-attr-scope-loader
如果 webpack 不熟,可以参考:http://github.com/xuxusheng/webpack-test
实际的项目例子可以参考(可以clone下来跑一跑):http://github.com/xuxusheng/html-attr-scope-loader-example
安装:
npm install html-attr-scope-loader --save-dev
html文件:
<link href="./index.scss">
<link href="./index.css">
<div>
<ul>
<li><p></p></li>
</ul>
</div>
css文件:
div {}
.title {}
div.demo {}
div.wrap ul.list li.item {}
.hover:hover {}
.after::after {}
div#article > ul::before ~ li, .xusheng::after, .xu > .sheng::before {}
转换后:
html 文件:
<div _7c1ac95d75>
<ul _7c1ac95d75>
<li _7c1ac95d75><p _7c1ac95d75></p></li>
</ul>
</div>
css 文件:
div[_7c1ac95d75] {}
.title[_7c1ac95d75] {}
div.demo[_7c1ac95d75] {}
div.wrap[_7c1ac95d75] ul.list[_7c1ac95d75] li.item[_7c1ac95d75] {}
.hover:hover[_7c1ac95d75] {}
.after[_7c1ac95d75]::after {}
div#article > ul[_7c1ac95d75]::before ~ li[_7c1ac95d75], .xusheng[_7c1ac95d75]::after, .xu[_7c1ac95d75] > .sheng[_7c1ac95d75]::before {}
loader: 'html-attr-scope?scopeLen=10&sourceMap'
scopeLen: 表示所生成的自定义属性(hash值)的长度,默认为10,可以省略。
sourceMap: 开启 css-loader 的 sourceMap 功能
webpack 的 loader 肯定是要结合 webpack 来使用。
默认采用 postcss 来支持 scss, 所有先要在 webpack 中配置好 postcss 以及其对 scss 的支持。
首先在 webpack.config.js 文件中设置如下:
config.module = {
loaders: [{
test: /\.html$/,
loader: 'html-attr-scope-loader'
}]
}
当引入了 html-attr-scope-loader 之后,对 css 的引入即可不再通过在 js 文件中采用 require('./xxx.css')
的方式。
在 html 文件中,加入 <link href='./xxx.css'>
标签即可。
默认支持 scss 文件,也是直接采用 <link href='./xxx.scss'>
标签即可。
html 文件和其所引入的 css 文件会被标记上同样的自定义属性[_xxxxxxxxxx]
,达到隔离的作用,防止不同模块间样式冲突。
第三方库的样式文件可以继续使用 require() 的方式引入。
默认会将 css/scss 中的所有选择器都加上自定义属性,这样会使所有的规则都模块化。
但是如果希望某一个选择器不被模块化怎么办?
在 scss文件中使用 :global
即可:
如:
:global(.xusheng) .xu > .sheng {}
:global {
.xu { }
.sheng { }
}
会变为:
.xusheng .xu[_xxxxxxxxxx] > .sheng[_xxxxxxxxxx] {}
.xu {}
.sheng {}
-
html 文件中的 link 标签会被移除。
-
html 文件中每一个标签都会被加上自定义属性。
-
css 文件中选择器后面会被加上相应的属性选择器。
-
如果选择器有多级的话,那么只会在每一级的最后面加上一个属性选择器,同样的,如果这一级存在ID选择器的话,就不会再在末尾加上属性选择器,例如:
.xuxusheng > .xusheng.sheng {}
会变为.xusheng[_xxxxxxxxxx] > .xusheng.xu[_xxxxxxxxxx]
, 而.xuxusheng > #xusheng.sheng {}
会变为.xuxusheng[_xxxxxxxxxx] > #xusheng.sheng {}
。 -
如果在伪元素后面加上属性选择器的话,样式会失效,如
.xusheng::after[_xxxxxxxxxx] {}
所以在遇到伪元素的时候,会将属性选择器向前移动一位,不在最后,如:.xusheng[_xxxxxxxxxx]::after
。因为对伪类以及伪元素的判定是基于一个冒号还是两个冒号的,所以在使用伪元素时尽量使用规范的两个冒号,尽管一个冒号浏览器也可以识别。
- 配合 angular 使用时,不要在 ng-src 中写相对路径来引用文件,比如:
<img ng-src="./avatar.png">
loaer在遇到 ng-src 属性时会忽略掉,并不会解析,注意!。
- 自定义属性具体是通过什么来决定的?
答:当在 js 文件中 require('./xxx.html')
时,在 html-attr-scope-loader
中会使用 nodejs
的 crypto
模块,根据当前 html 文件中的字符串生成一串 hash
值,此值前面在加上下划线之后即为自定义属性。
- 为什么自定义属性前面要加上下划线?
答:因为如果不加下划线的话,有时候生成的hash值会是数字开头的,而 html 中采用数字开头的自定义属性是 invalid 的。