组件中样式的冲突

组件中定义的样式,默认是全局都有效的,vue最终会把这些样式汇总到一起。

组件的样式最终汇总出来的顺序,取决于在父组件中引入的顺序。

例如:School中定义的样式:

  1. <template>
  2. <div class="demo">
  3. <h2>学校名称:{{name}}</h2>
  4. <h2>学校地址:{{address}}</h2>
  5. <br>
  6. </div>
  7. </template>
  8. <style>
  9. .demo {
  10. background-color: skyblue;
  11. }
  12. </style>

在Student.vue中定义的样式:

  1. <template>
  2. <div class='demo'>
  3. <h2>学生姓名:{{name}}</h2>
  4. <h2>学生性别:{{sex}}</h2>
  5. </div>
  6. </template>
  7. <style>
  8. .demo {
  9. background-color: orange;
  10. }
  11. </style>

如果在App组件中同时引入了School、Student两个组件,则这两个组件的样式都会被引入。因为这两个组件的模板class都叫demo,就会产生冲突。

模板最终使用的background-color取决于哪个组件在App中最后被引入:

  1. import Student from './components/Student'
  2. // 先引入Student,然后引入School,则最后的background-color使用的是School中的样式
  3. import School from './components/School'

如果改为先引入School再引入Student,样式就会使用Student定义的样式:

  1. import School from './components/School'
  2. // 最后引入Student组件,则最后冲突的样式使用的是Student的样式
  3. import Student from './components/Student'

限制样式作用域

使用scoped属性限制该样式只对当前组件有效:

  1. <!-- 使用了scoped限制了作用域,该样式只会对当前组件有效 -->
  2. <style scoped>
  3. .demo {
  4. background-color: orange;
  5. }
  6. </style>

实现原理:Vue会给该组件添加一个data-v-随机数的属性,然后在样式上也添加该属性的筛选:

.data[data-v-xxxxxx]。这样这个样式就只会对这个组件有效了。

加了scoped之后,这个样式只会对当前组件有效,对当前组件引入的子组件无效。

使用预编译语言编写样式

可以使用<style>lang属性声明该样式使用的语言。

例如:

  1. <!-- 声明该样式使用css编写 -->
  2. <style lang='css'></style>

如果要使用 less 编写样式,则需要设置:(不配置时,默认使用的css)

  1. <style lang='less'></style>

除此之外,还需要安装 less-loader:

最新版的less-loader只支持webpack5,但是目前Vue脚手架中引入的webpack是4.46版,所以不能直接下载最新版的less-load,需要加上版本限制。

  1. # 查看webpack的所有版本
  2. npm view webpack versions
  3. # 查看less-loader的所有版本
  4. npm view less-loader versions
  5. # 限制安装的less-load版本为7.x
  6. npm i less-loader@7

如果报错缺少less,则需再安装less:

  1. npm i less