前端工程中的样式隔离及原理
平常开发vue项目时,我们经常会在style标签中加上scoped这样一个属性,我们都知道这个是为了样式隔离,那它是怎么做到样式隔离的呢?除了这种方式还有别的方式可以做到样式隔离吗?除了vue别的前端框架里是怎么实现样式隔离的呢?嘿嘿,今天就详细了解一下吧!
1、CSS Scoping 样式作用域
在style标签中添加scoped属性
原理:在编译过程中,vue会为所有有scoped属性的组件加上一个特殊的属性选择器,这个唯一的属性选择器是根据当前组件的唯一标识生成的,一般是在组件的根元素上添加一个data-v-xx 的属性,并将这个属性自动添加到组件中的每个元素上。同时,它会修改 CSS 选择器,使其匹配这些属性,从而实现样式的局部化。其中xx 是一个哈希值或者组件标识。
编译前:
<template>
<div class="con">
<div class="button">Click me</div>
</div>
</template>
<style scoped>
.con {
background-color: #f0f0f0;
}
.button {
color: red;
}
</style>
编译后:
<div class="con" data-v-123abc >
<div class="button" data-v-123abc >Click me</div>
</div>
.con [data-v-123abc] {
background-color: #f0f0f0;
}
.button [data-v-123abc] {
color: red;
}
这种方式实现了组件级别的样式隔离,让每个组件的样式都被限制在自己的作用域内,不会影响其他组件或全局样式。使得组件可以更好地封装和重用,同时避免了样式冲突的可能性。
2、使用CSS Modules 实现组件级样式隔离
可以将CSS文件命名为 xxx.module.css ,然后在组件中通过import 的方式引入样式文件。隔离的原理是 :CSS Modules 会为每个类名生成一个独一无二的哈希值。
编译前:
.button {
color: green;
}
import styles from './Button.module.css';
function Button() {
return <button className={styles.button}>Click me</button>;
}
编译后:
.button__button__2x9pG {
color: green;
}
3、使用命名空间
为每个组件或模块添加唯一前缀或命名空间,避免样式冲突。
4、Shadow DOM
Shadow DOM 是 Web Components 的一部分,它可以创建一个完全封闭的 DOM 子树,其中的样式不会泄漏到外部。
<my-component></my-component>
<script>
class MyComponent extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
.button {
color: purple;
}
</style>
<button class="button">Click me</button>
`;
}
}
customElements.define('my-component', MyComponent);
</script>
在这个例子中,<my-component>
组件的样式被完全隔离在 Shadow DOM 内部,不会影响到页面上的其他元素。
5、CSS-in-js
一些js库提供了将CSS写入js的功能,如styled-components 、emotion等。
import styled from 'styled-components';
const Button = styled.button`
color: pink;
padding: 20px;
`;
function App() {
return <Button>Click me</Button>;
}