前端工程中的样式隔离及原理

平常开发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>;
}
posted @ 2024-03-19 13:15  icon-icon  阅读(20)  评论(0)    收藏  举报