持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天, 点击查看活动详情
引言
在 vue-cli组件化开发中,有时候注册使用的组件会渲染到index.html中指定的div区域中,这就导致了样式间可能会因重名或等等原因发生样式冲突
接下来我们简单回顾一下组件开发及样式冲突问题。
组件化开发中的样式冲突
我们初始化了一个vue-cli 项目,并在components目录下创建up.vue(上组件),down.vue(下组件)和all.vue
上组件代码
<template>
<div class="upStyle">
{{updata}}
</div>
</template>
<style lang="less">
.upStyle {
width: 300px;
height: 300px;
background-color: greenyellow;
}
</style>
<script>
export default {
data(){
return {
updata:"这是上组件"
}
}
}
</script>
下组件代码
<template>
<div class="downStyle">
{{downdata}}
</div>
</template>
<style lang="less">
.downStyle {
width: 300px;
height: 300px;
background-color: rebeccapurple;
}
</style>
<script>
export default {
data(){
return {
downdata:"这是下组件"
}
}
}
</script>
全局组件代码
<template>
<div>
<div class="data">
{{allData}}
</div>
</div>
</template>
<style scoped>
div {
color: brown;
}
.data {
width: 60px;
height: 60px;
}
</style>
<script>
export default {
data(){
return {
allData:"All组件"
}
}
}
</script>
接下来我们在App.vue中注册左右组件
<script>
import up from "@/components/up.vue";
import down from '@/components/down.vue';
export default {
components:{
up,down
}
}
</script>
上面是注册的核心代码,引入并注册之后就可以将 up 和 down 作为标签在template中使用。
import all from '@/components/all.vue';
Vue.component('MyCount',all);
main.js的全局注册及使用如上,
接下来我们开始先简单解释一下,因为我们这里主要目的是剖析scoped的底层原理,这里我们不详细解释删去scoped和加上的区别。只是在下面附上冲突和解决样式冲突后的对比图。
这是冲突的效果
可以看到下部分字体依旧是黑色,并没有因全局组件的引入而改变颜色,也就是没有发生样式冲突。
接下来我们删去scoped,看看效果。
可以看到发生了样式冲突吗,下组件并没有引入这个全局组件all.vue但是同样字体颜色发生了改变。
这就是样式冲突,有时候样式冲突会非常影响我们的开发。
scoped的底层原理
接下来我们不使用scoped,来通过纯粹的css来解决这个问题。
先回忆一下css中几个选择器。
组合 Combinators
名称 语法 说明 示例
直接组合 AB 满足A同时满足B input.error, a.error
后代组合 A B 选中B,如果他是A的子孙 nav a b 在 a里面 只要所有的a标签 出现在 nav下面 不管隔了多少级 都会被选中
亲子组合 A>B 选中B,如果他是A的子元素 section>p 必须直接
兄弟选择器 A~B 选中B,如果他在A后且和A同级 h2~p 同级 同一个父级 并列
相邻选择器 A+B 选中B,如果他紧跟A后面 h2+p 紧跟着的兄弟选择器
我们简单回顾一下选择器,可能很多聪明的基础很好的同学已经猜到了其中的底层原理。
没错,我们就是通过组合Combinators来选择指定的样式。
从而解决我们的样式冲突问题。
接下来我们开始操作。
接下来我们开始改变我们的all.vue组件
<template>
<div>
<div class="data">
{{allData}}
</div>
</div>
</template>
<style>
.allStyle div {
color: brown;
}
.allStyle .data {
width: 60px;
height: 60px;
}
</style>
<script>
export default {
data(){
return {
allData:"All组件"
}
}
}
</script>
改变的部分:
可以看到,这里我们并没有使用 scoped属性,只是单纯的使用了css的Combinators组合来进行选择,这里我们使用的后代选择器。
up.vue中我们也需要做一点点改动。
代码如下:
<template>
<div class="upStyle">
{{updata}}
<MyCount class="allStyle"></MyCount>来了
</div>
</template>
<style lang="less">
.upStyle {
width: 300px;
height: 300px;
background-color: greenyellow;
}
</style>
<script>
export default {
data(){
return {
updata:"这是上组件"
}
}
}
</script>
我们重点看一下改变的部分
我们先简单观察一下代码,我们在上组件中引入的全局组件,结合之前的我们做的后代选择器,所以这里我们需要加上之前加的 allStyle 类
这样我们赋予特定属性的元素才会被选择到,而其他的并不会被选到(受到影响)
可以看到,我们的额外又加入了allStyle类,让他被我们选择到
那么我们可以发现scoped的底层原理了,每个加入scoped的属性的组件,都会赋予一个独特的,关键词,本质上其实就是css的组合选择器。
这就是scoped的底层原理。