scoped原理及使用

225 篇文章 1 订阅
108 篇文章 0 订阅

一、什么是scoped,为什么要用
在vue文件中的style标签上,有一个特殊的属性:scoped。
当一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,通过该属性,可以使得组件之间的样式不互相污染。

二、scoped的原理
1、为组件实例生成一个唯一标识,给组件中的每个标签对应的dom元素添加一个标签属性,data-v-xxxx
2、给<style scoped>中的每个选择器的最后一个元素添加一个属性选择器,原选择器[data-v-xxxx],如:原选择器为.container #id div,则更改后选择器为.container #id div[data-v-xxxx]

注意:是加在最后一个元素上的!

//.a为大div父组件 .b为子组件根元素 .c为子组件内的子元素
 .a .b .c{//多层
    color:red
  }
  //会渲染成
  .a .b .c[data-v-2311c06a]{
    color:red
  }

三、示例
转译前的vue代码

<template>
	<div class="example">hello world</div>
</template>
<style scoped>
.example {
	color: red;
}
</style>

<template>
	<div class="example" data-v-49729759>hello world</div>
</template>
<style scoped>
.example[data-v-49729759] {
	color: red;
}
</style>

二: /deep/深度作用选择器
1.说明
通过上面的讲解,我们了解到scope主要通过文件指纹控制作用域范围。而针对每个样式的定义,只能出现一个文件指纹。我们看如下代码:

<template>
  <div class="container">
    <span>1111</span>
  </div>
</template>
<script lang=ts setup>
</script>
<style lang=scss scoped>
.container{
    background-color: lightblue;
    width: 100px;
    height: 100px;
    .abc{
        background-color: #fff;
        .def{
            color: red;
        }
    }
}
</style>

这里我们使用的是scss语法,我们看一下编译后的呈现形式:
在这里插入图片描述
通过截图我们发现会在每个样式后面都加上一个文件指纹的属性。
那我现在有个需求,我想把文件指纹加到中间该怎么办呢?此时,v-deep就派上用途了。看下面代码:

<template>
  <div class="container">
    <span>1111</span>
  </div>
</template>
<script lang=ts setup>
</script>
<style lang=scss scoped>
.container{
    background-color: lightblue;
    width: 100px;
    height: 100px;
    ::v-deep.abc{
        background-color: #fff;
        .def{
            color: red;
        }
    }
}
</style>

在这里插入图片描述
其实/deep/ 编译后的结果将会是一个属性选择器

2. 案例
通过上面的讲解,那他究竟有什么作用呢?下面我们通过一个案例体会他的真正作用。
再vue的世界中,我们很多时候会使用第三方库,比如element-ui等。如果我想该里面的样式,之前好多同事会把样式放到全局中,这样显而易见容易污染其他的元素,此时,/deep/就会大显身手。

我们暂时选择ant-design库作为测试。
index.vue

<template>
  <div class="container">
    <a-checkbox class="check" v-model:checked="checked">Checkbox</a-checkbox>
  </div>
</template>

<script lang=ts setup>
import { ref } from 'vue';
const checked = ref(true)
</script>

<style lang=scss scoped>
.container{
    background-color: lightblue;
    width: 500px;
    height: 510px;
}
</style>

此时,我们看一下生成的代码片段:
在这里插入图片描述
在这里插入图片描述
假如我现在有个需求,想把复选框中间的蓝色变成红色,很容易想到需求修改ant-checkbox-inner的样式,如下代码:

<style lang=scss scoped>
.container{
    background-color: lightblue;
    width: 500px;
    height: 510px;
    .check{
      .ant-checkbox-inner{
        background-color: red;
      }
    }
}
</style>

然而,并没有生效,我们看一下生成的代码:
在这里插入图片描述
我们发现在ant-checkbox-inner后面加了一个文件指纹。而实际这是第三方库(也就是已经打包好的文件),里面的标签根本不会出现文件指纹。这样就导致我们写的样式文件不能作用于ant-checkbox-inner上。此时,我们很容易想到要把样式变成全局。

<style lang=scss>
.container{
    background-color: lightblue;
    width: 500px;
    height: 510px;
    .check{
      .ant-checkbox-inner{
        background-color: red;
      }
    }
}
</style>

在这里插入图片描述
虽然样式生效了,但是出现了最严重的问题,它会污染到其他vue组件使用的checkbox组件。此时v-deep就登场了。代码如下:

<style lang=scss scoped>
.container{
    background-color: lightblue;
    width: 500px;
    height: 510px;
    .check{
      /deep/ .ant-checkbox-inner{
        background-color: red;
      }
    }
}
</style>

在这里插入图片描述

再看样式表,发现给check加了文件指纹,check是我们vue组件的标签,因此编译的时候会加上文件指纹。这样就完美解决了问题。

  • 24
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值