Vue中的scope详解以及使用/deep/解决组件样式不起作用

一.scope

在vue中,我们为了避免父组件的样式影响到子组件的样式,会在style中加<style scoped>,这样父组件中如果有跟子组件相同的class名称或者使用选择器的时候,就不会影响到子组件的样式。

具体来说,使用 scoped 属性后,你在样式中定义的选择器会被自动转换为带有特定哈希前缀的选择器,以确保它们只影响当前组件的元素。这种方式可以有效地避免全局样式冲突问题,使得组件的样式更加独立和可预测。

①我们在组件加了 scoped 之后,组件的根元素的样式会自动添加一个hash值。

 例子:比如我现在新建了一个名字为homeIndex的vue组件,该组件的根元素为类名为home-container的div 

<template>
  <div class="home-container">
    <van-button>哈哈哈</van-button>
  </div>
</template>
 
<script>
export default {
  name: 'homeIndex',
 
  data() {
    return {
      active: 2
    };
  },
 
  mounted() {
 
  },
 
  methods: {
 
  }
}
</script>
 
<style lang="less" scoped>
</style>

打开控制台:可以看到组件的根元素的style样式中就添加了哈希值

在这个示例中,使用了 scoped 属性,所以 .home-container样式会被转换为类似 .home-container[data-v-f3f3eg9] 的选择器,其中 data-v-f3f3eg9 是一个哈希值,用于确保样式只作用于当前组件。

需要注意的是,scoped 属性只对当前组件的直接子元素起作用。如果你希望样式作用于子组件内部的元素,你需要在子组件中也使用 scoped 属性。

②在父组件中,最多只能影响子组件的根元素,意思就是在父组件的样式中只能修改子组件根元素的样式 

 例子:现在我们在home-container组件引入了van-tabs组件,并起类名为channal-tabs,那么现在home-container为父组件,van-tabs组件为子组件,而现在我们又通过在父组件修改子组件的根元素的样式  .channal-tabs { color: red;},那么这样是可以在父组件中修改子组件的样式的。

<template>
  <div class="home-container">
    <!-- 频道栏 -->
    <van-tabs v-model="active" animated swipeable class="channal-tabs">
      <van-tab title="标签 1">内容 1</van-tab>
      <van-tab title="标签 2">内容 2</van-tab>
      <van-tab title="标签 3">内容 3</van-tab>
      <van-tab title="标签 4">内容 4</van-tab>
      <van-tab title="标签 4">内容 4</van-tab>
      <van-tab title="标签 4">内容 4</van-tab>
      <van-tab title="标签 4">内容 4</van-tab>
      <van-tab title="标签 4">内容 4</van-tab>
      <van-tab title="标签 4">内容 4</van-tab>
    </van-tabs>
    <!-- 频道栏 -->
  </div>
</template>
 
<script>
export default {
  name: 'homeIndex',
 
  data() {
    return {
      active: 2
    };
  },
 
  mounted() {
 
  },
 
  methods: {
 
  }
}
</script>
 
<style lang="less" scoped>
.home-container {
 
  .channal-tabs {
    color: red;
  }
}
</style>

打开控制台:可以看到父组件的样式中只能修改子组件根元素的样式

 ③注意!注意!注意!在父组件中,最多只能影响子组件的根元素,而不能修改子组件根元素更里层的样式 

例子:比如我们在父组件home-container修改子组件channal-tabs更深层的元素van-tab__pane的样式.van-tab__pane {  color: red;}这样是无法修改的

<template>
  <div class="home-container">
    <!-- 频道栏 -->
    <van-tabs v-model="active" animated swipeable class="channal-tabs">
      <van-tab title="标签 1">内容 1</van-tab>
      <van-tab title="标签 2">内容 2</van-tab>
      <van-tab title="标签 3">内容 3</van-tab>
      <van-tab title="标签 4">内容 4</van-tab>
      <van-tab title="标签 4">内容 4</van-tab>
      <van-tab title="标签 4">内容 4</van-tab>
      <van-tab title="标签 4">内容 4</van-tab>
      <van-tab title="标签 4">内容 4</van-tab>
      <van-tab title="标签 4">内容 4</van-tab>
    </van-tabs>
    <!-- 频道栏 -->
  </div>
</template>
 
<script>
export default {
  name: 'homeIndex',
 
  data() {
    return {
      active: 2
    };
  },
 
  mounted() {
 
  },
 
  methods: {
 
  }
}
</script>
 
<style lang="less" scoped>
.home-container {
  .channal-tabs {
    .van-tab__pane {
      color: red;
    }
  }
}
</style>

打开控制台:可以看到样式并没生效

 如果我们需要在父组件中修改子组件的样式怎么办? 

这时候就需要使用/deep/,修改子组件的样式代码

<style lang="less" scoped>
.home-container {
  /deep/.channal-tabs {
    .van-tab__pane {
      color: red;
    }
  }
}
</style>

打开控制台:

可以看到成功在父组件中修改子组件更深层的样式 

二、>>>、/deep/以及::v-deep(意思是更深层的意思) 

 以上三种的效果均是在父组件改变子组件更深层元素的样式。  

  一些预处理器(例如Sass)可能无法正确解析>>>。在这些情况下,可以改用/deep/::v-deep组合器,两者都是它的别名,并且和>>>工作原理完全相同。

三.总结

 1.给组件加scope后,该组件的根元素的样式会自动添加哈希值,表示该组件的样式不会影响其他组件(一般第三方组件,比如vant组件都会有哈希值)
2.默认只能在父组件修改子组件根元素的样式,如果想修改子组件更深层元素的组件的样式,就给子组件样式加/deep/(浏览器兼容性最好)

猜你喜欢

转载自blog.csdn.net/weixin_42017221/article/details/134174132