原文连接:https://github.com/AlloyTeam/AlloyTouch/wiki/Scoped-CSScss
问:什么是Scoped CSS规范?webpack
Scoped CSS规范是Web组件产生不污染其余组件,也不被其余组件污染的CSS规范。git
面对组件化的普及,组件的复用很广泛的需求,然而CSS相互污染是常常碰见的问题,创建规范让开发者放心使用各类组件,甚至跨生态的组件是颇有必要的一件事情。github
方案一:
若是用webpack的话,能够参考css-loader的这个功能:web
一段hash + 组件名,这个可能兼顾了辨识度 + 命名污染的问题。sass
方案二:app
用webpack和scss,less写成模块化css就能够必定程度避免CSS污染,不能彻底避免less
方案三:样式规范上,使用与组件同名的嵌套命名空间dom
若是只用本身的生态能够这么搞,可是有的时候会引入第三方生态,第三方和本身的命名空间同样仍是颇有可能,好比scroller插件,社区里也有不少scroller插件loading uplader插件等等。ide
这里仍是会有污染的状况,由于:
因此得出:
用意念或者规范约定否则注入程序自动化避免冲突
好处:
若是把这个过程放在构建过程就是工程问题。可是组件单独抽离出来给第三方用,其实就是组件自己的问题。总之要保证:
;(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插件里开始实施,并打算推广开来。
你有什么好的想法可让跨生态跨项目跨技术栈的组件复用更加惬意,能够交流交流。