Vue3的三种样式控制及实现原理

你好同学,我是沐爸,欢迎点赞、收藏、评论和关注。

Vue3中一共有三种样式控制,分别是全局样式控制、局部作用域样式控制和深度样式控制,今天我们一起看下这三种样式控制的使用,以及实现的原理是什么。

一、全局样式控制

在组件中定义的样式,默认是全局有效的。也就是说,无论对于根组件App.vue,还是普通的视图组件或公共组件,在style标签中定义的样式都是全局样式。

原因在组件标签中的样式,在打包时没有额外添加其他限制条件,自动成为了全局样式。

App.vue

<template>
  <header>
    <img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />

    <div class="wrapper">
      <HelloWorld msg="You did it!" class="p-20" />

      <nav>
        <RouterLink to="/">Home</RouterLink>
        <RouterLink to="/about">About</RouterLink>
      </nav>
    </div>
  </header>
  
  <RouterView />
</template>

<style>
a {
  color: red !important;
}
</style>

示例中的样式会导致全局的a标签都是红色。

image.png

二、局部作用域样式控制

全局样式的弊端也很明显:样式很可能产生冲突和覆盖。局部作用域样式只在当前组件内部生效,不影响其他组件(可能影响子组件的根标签,如果你在组件上添加class并定义样式的话)。使用起来也很方便,只需要在style标签上添加scoped属性即可。

App.vue

<template>
  <header>
    <img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />

    <div class="wrapper">
      <HelloWorld msg="You did it!" class="p-20" />

      <nav>
        <RouterLink to="/">Home</RouterLink>
        <RouterLink to="/about">About</RouterLink>
      </nav>
    </div>
  </header>
  
  <RouterView />
</template>

<style scoped>
a {
  color: red !important;
}
.p-20 {
  padding: 20px;
}
</style>

HelloWorld.vue

<template>
  <div class="greetings">
    <h1 class="green">{{ msg }}</h1>
    <h3>
      You’ve successfully created a project with
      <a href="https://vitejs.dev/" target="_blank" rel="noopener">Vite</a> +
      <a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
    </h3>
  </div>
</template>

<style scoped>
a {
  color: green;
}
.greetings {
  padding: 20px;
}
</style>

App.vue中定义的样式,a标签的样式只在App.vue中生效,不会影响HelloWorld.vue中的a标签,而.p-20则会影响HelloWorld.vue的根标签的样式。

局部作用域样式的原理并不复杂,Vue内部主要做了两件事情:

(1)一旦style声明为scoped,当前组件的所有标签和子组件的根标签,都会自动动添加名为 data-v-xxx 的唯一标识。

(2)在打包运行的页面中,样式选择器的最右侧添加了名为data-v-xxx 的属性选择器,导致只有该属性的元素才会具有该属性选择器的样式。

image.png

三、深度样式控制

如何让组件的局部样式影响子组件的子标签呢?这就需要使用Vue提供的深度作用域选择器来实现。只需要将要修改的标签用":deep()"包裹即可。

例如我们要在App.vue中修改HelloWorld.vue组件的h1标签的下外边距,App.vue可以这样设置:

<template>
  <header>
    <img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />

    <div class="wrapper">
      <HelloWorld msg="You did it!" />

      <nav>
        <RouterLink to="/">Home</RouterLink>
        <RouterLink to="/about">About</RouterLink>
      </nav>
    </div>
  </header>
  
  <RouterView />
</template>

<style scoped>
.wrapper :deep(.green) {
    margin-bottom: 30px;
}
</style>

深度样式控制的实现原理是什么?deep声明将选中标签原本具有的data-v-xxx 的属性选择器给移除了。如果不明白,详细看下方的截图:

image.png

四、总结

你有可能看着本篇博客的内容有些眼熟,如果你读过《剑指Vue3–入门到实践》,内容来自4.3章节。今天的分享更像是一个学习笔记,分享的示例和语言组织都是个人感悟,并非照搬原文。

好了,分享结束,谢谢点赞,下期再见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沐爸muba

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值