你好,我是沐爸,欢迎点赞、收藏和关注。个人知乎
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
标签都是红色。
二、局部作用域样式控制
全局样式的弊端也很明显:样式很可能产生冲突和覆盖。局部作用域样式只在当前组件内部生效,不影响其他组件(可能影响子组件的根标签,如果你在组件上添加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
的属性选择器,导致只有该属性的元素才会具有该属性选择器的样式。
三、深度样式控制
如何让组件的局部样式影响子组件的子标签呢?这就需要使用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
的属性选择器给移除了。如果不明白,详细看下方的截图:
四、总结
你有可能看着本篇博客的内容有些眼熟,如果你读过《剑指Vue3–入门到实践》,内容来自4.3章节。今天的分享更像是一个学习笔记,分享的示例和语言组织都是个人感悟,并非照搬原文。
好了,分享结束,谢谢点赞,下期再见。