博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Scoped CSS规范草案
阅读量:6509 次
发布时间:2019-06-24

本文共 3322 字,大约阅读时间需要 11 分钟。

原文链接:

写在前面

问:什么是Scoped CSS规范?

Scoped CSS规范是Web组件产生不污染其他组件,也不被其他组件污染的CSS规范。

面对组件化的普及,组件的复用很普遍的需求,然而CSS相互污染是经常遇见的问题,建立规范让开发者放心使用各种组件,甚至跨生态的组件是很有必要的一件事情。

目前业界的一些方案

方案一:

如果用webpack的话,可以参考css-loader的这个功能:

105416-20161226160741601-1648420713.png

一段hash + 组件名,这个可能兼顾了辨识度 + 命名污染的问题。

方案二:

用webpack和scss,less写成模块化css就可以一定程度避免CSS污染,不能完全避免

方案三:样式规范上,使用与组件同名的嵌套命名空间

如果只用自己的生态可以这么搞,但是有的时候会引入第三方生态,第三方和自己的命名空间一样还是很有可能,比如scroller插件,社区里也有很多scroller插件loading uplader插件等等。

现有方案的局限性

这里还是会有污染的情况,因为:

  • 模块化的粒度是大于等于组件化粒度,意思就是一个模块可能有多个组件
  • 非less和sass项目下的组件怎么保证
  • 难以保证不污染第三方组件
  • 难以保证不被第三方组件污染
  • 同名组件的问题
  • 组件在第三方项目使用的问题
  • 组件自身生态闭环的问题

所以得出:

用意念或者规范约定不然注入程序自动化避免冲突

好处:

  • 能保证不污染别的组件并且不被被的组件污染可以更放心的复用
  • Scoped CSS规范是运行时产生唯一id~~ 永远不会css碰撞
  • 返回的这个id那个指定给组件的顶层div就行,实施简单

如果把这个过程放在构建过程就是工程问题。但是组件单独抽离出来给第三方用,其实就是组件本身的问题。总之要保证:

  • 不污染第三方的项目或组件
  • 不被第三组件或项目污染(由于是层叠样式,这个无法完全保证)

Scoped CSS代码

;(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 = '
', 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;})();

Scoped CSS实施

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规范已经在插件里开始实施,并打算推广开来。

你有什么好的想法可以让跨生态跨项目跨技术栈的组件复用更加惬意,可以交流交流。

转载地址:http://rybfo.baihongyu.com/

你可能感兴趣的文章
多线程问题(JVM重排序)
查看>>
LeetCode 459 Repeated Substring Pattern
查看>>
POJ 3268 Silver Cow Party
查看>>
EMLS项目推进思考
查看>>
Eclipse快捷键 10个最有用的快捷键
查看>>
2018-2019-1 20165302 实验五 通讯协议设计
查看>>
Golang 知识点总结
查看>>
JAVA 8 特性
查看>>
算法设计 - LCS 最长公共子序列&&最长公共子串 &&LIS 最长递增子序列
查看>>
WebService之Axis2快速入门(7): Spring与axis整合发布为WebServic
查看>>
Uliweb查看模板调用关系
查看>>
C#与PHP通信压缩
查看>>
关于 Linux
查看>>
图文解析五大外链误区
查看>>
ios开发之导航控制器的原理
查看>>
《Netkiller Blockchain 手札》Hyperledger Fabric Java SDK Demo
查看>>
Spring cloud 安全部署与性能优化
查看>>
querySelector 和 querySelectorAll区别
查看>>
Linux系统_Centos7下安装Nginx
查看>>
《PHP和MySQL Web 开发》 第12章 MySQL高级管理
查看>>