CSS 隔离方案

子应用之间的样式隔离方案

  • Dynamic Stylesheet 动态样式表,档应用切换时移除老应用样式,添加新应用样式

1 主应用和子应用之间的样式隔离

1.1 BEM(Block Element Modifer) 约定项目前缀

  • BEM 本质上是css的一种命名方案,是最流行的命名规则之一

    • Block: 块, 一般是元素的父级模块作为前缀,命名规范.block
    • Element: 元素, 命名规范,元素名称可以包含拉丁字母,数字,破折号和下划线.block__element
    • Modifer: 修饰符,命名规范,修饰符名称可以包含拉丁字母,数字,破折号和下划线,.block--modifier
  • BEM 特点:

    • 复杂甚至稍显冗长的类名极大减少了类名重复的可能性
    • 每个块理的一类元素的样式对应一个类名。如此,一个元素对应一个类名,减少了子选择器或者后代选择器的使用,提升了css的性能
    • css 类名的命名更加语义化,更容易读懂
    • 可复用性高
.block {}
.block__element {}
.block--modifier {}

1.2 CSS-Modules 打包时生成不冲突的选择器名

  • css modules 允许我们想import一个js模块一样的去引用css模块。每个css文件都是一个独立的模块,每个类名都是该模块所导出对象的一个属性。通过这种方式,便可以在使用时明确的指定所引用的css样式。
  • css modules 在打包时会自动将id和class混淆成全局唯一的hash值,从而避免了发生命名冲突的问题
  • css modules 的特点:
    • 作用域: 模块中的名称默认都属于本地作用域,定义在:local中的名称属于本地作用域,定义在:global中的名称属于全局作用域,全局名称不会被变异成哈希字符串
    • 命名:对于本地类名称,css modules 建议使用camelCase方式来命名,这样会使js文件更干净,即style.className.
    • 组合:使用compose属性来继承另一个选择器的样式,这与sass的@extend规则类似
    • 变量: 使用@value来定义变量,不过需要安装Postcss 和 postcss-modules-values插件来支持
/* 全局样式 */
// index.css
:global(.title) {}
.box {...}

/* 引用方式 */
// App.js
import React from 'react'
import styles from './index.css'
export default function App() {
	return (
		<div className={styles.box}>
			<h3 className="title">use css modules<h3>
		</div>
	)
}

/* webpack 打包之后的编译结果 */
<div className="style__box-ht21N">
	<h3 className="title">use css modules</h3>
</div>
  • 怎么在项目中启用css modules? (配置webpack 中的 css-loader)
// webpack.config.js
module.exports = {
...
{
	test: /\.(c|sa|sc)ss$/i,
	exclude: /node_modules/,
	use: [
		'style-loader',
		{
			loader: 'css-loader',
			options: {
				importLoaders: 2,
				// 开启 css modules
				modules: true,
				localIdentName; '[path][name]__[local]--[hash:base64:5]'
			}
		},
		'postcss-loader',
		'sass-loader',
	]
}
...
}

1.3 Shadow DOM 真正意义上的隔离

  • 通常情况下,DOM tree 分为两类: Light tree(一般的DOM树, 由HTML元素组成); Shadow tree(一个隐藏的DOM子树,不在HTML 显示)

    • 如果一个元素同时拥有两种DOM tree, 则浏览器只渲染Shadow tree
  • 通常在自定义元素中使用Shadow tree, 目的是为了隐藏组件内部结构和有效的样式

  • Shadow DOM 允许将隐藏的DOM树附加到常规的DOM树中,它以shadow root 节点为起始根节点,在这个根节点的下方,可以是任意元素,和普通的dom元素一样

  • 通过调用element.attachShadow({mode “open”/“close”}) 来创建一个Shadow root

    • 每个元素中只能有一个shadow root
    • element 原属必须是自定义元素,或者是以下元素中其中一个: articleasideblockquotebodydivfooterh1~h6headermainnavpsectionspan。其他元素不能容纳shadow tree
    • mode 选择的值为"open"和"close", open时, shadow root 可以通过element.shadowRoot访问; close时,element.shadowRoot 永远为null
  • shadow dom 是元素对于light dom 中的querySelector 不可见。实际上,shadow DOM 中的元素可能与light dom 中的某些元素的id冲突。这些元素必须在shadow tree 中独一无二

  • shadow dom 有自己的样式,外部样式规则不会在shadow中生效

  • 获取shadow dom 内部元素,我们可以从树内部查询

  • 拥有自己的id空间

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Shadow DOM use</title>
	</head>
	<script>
		customElements.define('shadow-use', class extends HTMLElement {
			connectedCallback() {
				const shadow = this.attachShadow({mode: "open"})
				shadow.innerHTML = "shadow dom 元素"
				const div = document.createElement("div")
				div.innerHTML = "light dom 元素"
				this.append(div)
			}
		})
	</script>
	<body>
		<shadow-use></shadow-use>
	</body>
</html

1.4 css-in-js (js 写css)

  • react 的出现,使关注点分离的开发原则不再使用,react 是组件结构,强制要求开发者将HTML、CSS、Javascript 写在一起,React 在js里面实现了对HTML和CSS 的封装,react对HTML的封装是JSX语言;对CSS的封装沿用了DOM的style属性对象,此外出现了一些用来加强react的css操作,这些第三方库统称为css-in-js,各种css-in-js 库将近有47种: https://github.com/MicheleBertoli/css-in-js
    • polished.js
    • aphrodite
    • babel-plugin-css-in-js
    • babel-plugin-pre-style
    • bloody-react-styled
    • csjs
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值