样式隔离是指各组件的样式相互独立、不发生冲突。Vue 提供了几种方式来实现样式的隔离:
- 作用域样式(Scoped Styles):
- 在 Vue 单文件组件中,可以使用 scoped 特性将样式限定于当前组件的作用域。
- 使用标签包裹的样式只对当前组件起作用,不会影响其他组件或全局样式。
- Vue 实现作用域样式的方式是通过给每个选择器添加一个唯一的属性选择器,以确保样式仅适用于当前组件。
- 原理是自动生成一个唯一的哈希值,并在编译时为该组件的所有html元素添加一个 data-v-xxxxx 属性,同时将组件内的所有 css 选择器末尾加上 [data-v-xxxxx] 属性选择器,保证样式仅在当前组件的元素上生效。
- CSS Modules:
- Vue 支持使用 CSS Modules 来实现样式的模块化和隔离。
- 在 Vue 单文件组件中,可以借助 module 特性启用 CSS Modules 功能,在样式文件中使用类似 :local(.className) 的语法来定义局部样式。
- CSS Modules 会自动生成唯一的类名,并在编译时将类名与元素关联起来,从而实现样式的隔离和局部作用域。
- CSS-in-JS 方案:
-
Vue 也可以结合 CSS-in-JS 库(如 styled-components、emotion 等)来实现样式的隔离。
-
使用这种方式,可以直接在组件代码中编写样式,并通过 JavaScript 对象或模板字符串的形式动态生成样式。
-
CSS-in-JS 方案将样式与组件紧密关联,实现了更高程度的样式隔离和可重用性。 这些方法各有特点,可以根据实际需求选择合适的方式来实现样式的隔离。作用域样式和 CSS Modules 是 Vue 官方提供的内置功能,而 CSS-in-JS 则是通过第三方库来实现。根据项目的规模和需求,选择适合的方式可以更好地管理和维护样式。
插曲:
vue的scoped样式冲突的问题,data-v-xxxxx 属性是通过.vue文件在项目中的相对路径path+文件名进行计算hash值的。在微前端中, 当主子应用中同时存在一个path和文件名相同时的.vue文件**(相同相对路径),**它的data-v-xxxxx算出来就是一样的,此时样式还是会冲突。
Vue2 和 Vue3 解决方式差不多
- 开发环境:根据 **文件相对路径** 计算 data-v-xxx;
- 生产环境:根据 **文件相对路径 + 文件内容** 计算 data-v-xxx;
? 为什么开发环境不把内容加入计算呢?开发阶段变化频繁,会造成构建时间加长。
解决方式是:在计算 data-v-xxx 时,加入 package.json 的项目名进行计算,这样能防止两个不同项目之间的样式冲突。