原文连接:github.com/AlloyTeam/A…css
问:什么是Scoped CSS规范?webpack
Scoped CSS规范是Web组件产生不污染其余组件,也不被其余组件污染的CSS规范。git
面对组件化的普及,组件的复用很广泛的需求,然而CSS相互污染是常常碰见的问题,创建规范让开发者放心使用各类组件,甚至跨生态的组件是颇有必要的一件事情。github
##目前业界的一些方案web
方案一:
若是用webpack的话,能够参考css-loader的这个功能:sass
一段hash + 组件名,这个可能兼顾了辨识度 + 命名污染的问题。app
方案二:less
用webpack和scss,less写成模块化css就能够必定程度避免CSS污染,不能彻底避免dom
方案三:样式规范上,使用与组件同名的嵌套命名空间ide
若是只用本身的生态能够这么搞,可是有的时候会引入第三方生态,第三方和本身的命名空间同样仍是颇有可能,好比scroller插件,社区里也有不少scroller插件loading uplader插件等等。
这里仍是会有污染的状况,由于:
因此得出:
用意念或者规范约定否则注入程序自动化避免冲突
好处:
若是把这个过程放在构建过程就是工程问题。可是组件单独抽离出来给第三方用,其实就是组件自己的问题。总之要保证:
;(function () {
function scoper(css) {
var id = generateID();
var prefix = "#" + id;
css = css.replace(/\/\*[\s\S]*?\*\//g, '');
var re = new RegExp("([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)", "g");
css = css.replace(re, function(g0, g1, g2) {
if (g1.match(/^\s*(@media|@keyframes|to|from|@font-face)/)) {
return g1 + g2;
}
if (g1.match(/:scope/)) {
g1 = g1.replace(/([^\s]*):scope/, function(h0, h1) {
if (h1 === "") {
return "> *";
} else {
return "> " + h1;
}
});
}
g1 = g1.replace(/^(\s*)/, "$1" + prefix + " ");
return g1 + g2;
});
addStyle(css,id+"-style");
return id;
}
function generateID() {
var id = ("scoped"+ Math.random()).replace("0.","");
if(document.getElementById(id)){
return generateID();
}else {
return id;
}
}
var isIE = (function () {
var undef,
v = 3,
div = document.createElement('div'),
all = div.getElementsByTagName('i');
while (
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
);
return v > 4 ? v : undef;
}());
function addStyle(cssText, id) {
var d = document,
someThingStyles = d.createElement('style');
d.getElementsByTagName('head')[0].appendChild(someThingStyles);
someThingStyles.setAttribute('type', 'text/css');
someThingStyles.setAttribute('id', id);
if (isIE) {
someThingStyles.styleSheet.cssText = cssText;
} else {
someThingStyles.textContent = cssText;
}
}
window.scoper = scoper;
})();复制代码
var id = scoper("h1 {\ color:red;\ /*color: #0079ff;*/\ }\ \ /* h2 {\ color:green\ }*/");复制代码
scoper返回的id,在组件的JS里面赋给包裹的DOM即可以。这里详细说下生成id的过程:
function generateID() {
var id = ("scoped"+ Math.random()).replace("0.","");
if(document.getElementById(id)){
return generateID();
}else {
return id;
}
}复制代码
经过Math.random获得随机数并通过处理,而后经过document.getElementById去查询页面上有没有同名ID,有的话则继续从新生成,没有的话就使用当前id。这里须要特别注意的是,好比一些弹出层插件,display hide的时候有的组件是直接从body里面移除,因此这就带来了CSS碰撞的可能性,因此这里Scoped CSS 规范强行约定:后插入的HTML,必定要通过scoper过程从新生成惟一id。
最后,Scoped CSS规范已经在AlloyTouch插件里开始实施,并打算推广开来。
你有什么好的想法可让跨生态跨项目跨技术栈的组件复用更加惬意,能够交流交流。