样式隔离
应用隔离:样式隔离
无论是刚才的快照沙箱还是另外的代理沙箱,其实都可以解决

样式隔离:Dynamic Stylesheet
当然动态样式表实现之后,我们还是没有解决主应用和主应用之间的样式冲突。实际上这个问题最好的手段还是通过一些工程化的手段来解,比如说a-
的前缀,应用b-
的前缀,你的框架应用也统一加个前缀。大家通过一些约定(比如约定大家都加上一个应用名的前缀)来避免冲突,这是非常有效的一个方案。尤其是主子应用之间的冲突,大部分情况下你只要保证主应用的样式做好改造,保证主应用的样式是很具象的规则,不会跟子应用冲突,那主子应用之间的冲突其实也解决了。不过这种方案终归是依赖约定,往往容易出纰漏。
样式隔离:工程化手段
当前
说明 | 优点 | 缺点 | |
---|---|---|---|
BEM | 不同项目用不同的前缀 |
简单 | 依赖约定,这也是耦合的一种,容易出纰漏 |
CSS Modules | 通过编译生成不冲突的选择器名 | 可靠易用,避免人工约束 | 只能在构建器与打包工具 |
CSS-in-JS | 基本彻底避免冲突 | 运行时开销,略缺失完整 |
样式隔离:Shadow DOM

简单的
<html>
<head></head>
<body>
<p id="hostElement"></p>
<script>
// 创建 shadow DOM
var shadow = document
.querySelector("#hostElement")
.attachShadow({ mode: "open" });
// 给 shadow DOM 添加文字
shadow.innerHTML = "<p>Here is some new text</p>";
// 添加CSS,将文字变红
shadow.innerHTML += "<style>p { color: red; }</style>";
</script>
</body>
</html>
我们也可以将
import React from "react";
import retargetEvents from "react-shadow-dom-retarget-events";
class App extends React.Component {
render() {
return <div onClick={() => alert("I have been clicked")}>Click me</div>;
}
}
const proto = Object.create(HTMLElement.prototype, {
attachedCallback: {
value: function () {
const mountPoint = document.createElement("span");
const shadowRoot = this.createShadowRoot();
shadowRoot.appendChild(mountPoint);
ReactDOM.render(<App />, mountPoint);
retargetEvents(shadowRoot);
},
},
});
document.registerElement("my-custom-element", { prototype: proto });
其实严格样是隔离代表
但是绝大部分情况下,你还是不能无脑的开启严格样式隔离的。原因之前的同学也已经提到过一些了,比如说你在使用一些弹窗组件的时候(弹窗很多情况下都是默认添加到了
我们提供了