Vue.js中scoped引发的CSS作用域探讨
前言
在Vue.js的组件化开发中,常常会对某个组件的style标签加上scoped属性,如<style lang='less' scoped>,这样做的目的在于使这个组件的样式不能轻易在其他地方被有意或无意修改,以达到封装的目的。值得注意的是,当我们进行组件嵌套时,常常需要修改子组件的默认样式,由组件封装引发的样式修改失效问题常常令人头痛,这其中涉及到的CSS作用域并不简单。因此,只有我们深入理解了Vue.js组件的CSS作用域问题,才能灵活地控制组件的样式以达到预期效果。本文正是基于此,对Vue.js组件的CSS作用域问题进行探讨。
为使文章更加易于理解,本文使用了案例进行展示,这些案例代码量小,结构简单,相当易读。同时为使结论更加具有一般意义,本文往往会在案例后进行总结,以便读者可以应用其中的规律。限于篇幅,部分结论没有展示效果,不过都经笔者测试可行,读者可自行测试,这并不复杂。
一、简单结构搭建
这里将要阐述一个简单的示例,父组件为App,子组件为Child。
子组件Child的定义文件Child.vue中代码如下:
<template>
<div id="child">
<h2>子组件h2</h2>
<h3>子组件h3</h3>
</div>
</template>
<script>
export default {
name: 'Child'
}
</script>
<style scoped>
h3 {
background-color: blue;
}
</style>
<style>
h2 {
background-color: blue;
}
</style>
可以看到,子组件Child有一个根元素div#child,根元素下有两个子元素h2和h3。在样式中设置h2和h3背景颜色也为蓝色,为便于比较,h3使用了scoped,h2则未使用scoped。
现在来看父组件App,它将嵌套子组件Child,代码如下:
<template>
<div id="app">
<Child/>
<h2>父组件h2</h2>
<h3>父组件h3</h3>
</div>
</template>
<script>
import Child from './components/Child'
export default {
name: 'App',
components: {
Child
}
}
</script>
<style scoped>
h3 {
background-color: red;
}
</style>
<style>
h2 {
background-color: red;
}
</style>
父组件App有一个根元素div#app,根元素中首先嵌套了子组件Child,然后是自有的h3和h2元素。在样式中设置h2和h3背景颜色为红色,同样,h3使用了scoped,h2则未使用scoped。
二、执果索因:先看效果
以上结构搭建完成后,我们很可能相当好奇:
两个
h3元素和h2元素分别显示何种背景颜色呢?他们的背景又是如何生效的呢?
我们先来看浏览器显示的效果:
这个结果可能令我们相当意外。子组件显示了子组件自身定义的样式,然而父组件的h2显示了子组件中对h2设置的样式,父组件的h3显示了父组件自身对h3的样式设置。这可能相当令人困惑,事实上,这正是我们要探讨的是否加scoped引发的样式的作用域问题。
三、html结构规律:data-v-x
我们先在浏览器中查看实际生成的html代码,如下:
<div data-v-04c2046b id="app">
<div data-v-10e5fd3c data-v-04c2046b id="child">
<h2 data-v-10e5fd3c>子组件h2</h2>
<h3 data-v-10e5fd3c>子组件h3</h3>
</div>
<h2 data-v-04c2046b>父组件h2</h2>
<h3 data-v-04c2046b>父组件h3</h3>
</div>
对于结构,我们应该不会有什么疑问,重点是其中html元素增加的data-v-x属性(x是一串数字)。
需要说明的是,这里的x不是特定的,可能随测试环境的不同而不同,上面是笔者测试时生成的情况。
可以发现,父组件App的根元素及子元素都增加了一个特定的[data-v-04c2046b]属性,子组件Child的根元素及子元素都增加了一个另一个特定的[data-v-10e5fd3c]属性,并且子组件根元素同时增加[data-v-04c2046b]属性和[data-v-10e5fd3c]属性`。
那么是否可以总结出结论:组件的根元素、子元素、子组件根元素都会增加data-v-x属性呢?
首先,并非所有组件都会增加data-v-x属性,事实上是否会增加data-v-x属性是由组件自身是否存在含scoped的style标签决定的。
也就是说,如果组件中不存在style标签或者虽然有style标签但是没有加scoped,那么组件的元素便不会增加data-v-x属性。因此,得出第1个结论:
结论1:data-v-x属性的增加是由组件中包含scoped的style标签引发。
第二个问题是,以上示例中,父组件和子组件都最多只有两层html结构,假使html元素嵌套得更深,那么组件的后代元素是否都会增加data-v-x属性呢,而不仅仅是子元素?
答案是肯定的,即结论2:
结论2:组件的根元素、组件自身的后代元素、子组件的根元素都会加上该组件特定的data-v-x属性。
这里,之所以用了“自身”这个词,原因在于子组件的后代元素虽然也会编译成父组件的后代元素,却不会加上父组件的data-v-x属性(下同)。
那么,子组件哪些元素会增加子组件特定的data-v-x属性呢?事实上,由结论2,只要将子组件看作一个没有子组件的父组件,那么不难得出:
结论3:子组件的根元素、子组件的后代元素会加上子组件特定的data-v-x属性。
四、CSS规律
现在,我们来看CSS样式是怎样作用的。
(一)不加scoped的style样式
父组件和子组件都设置了h2元素的样式,对于父组件和子组件的h2元素,起作用的都是子组件的样式设置,即:
h2 {
background-color: blue;
}
同时,浏览器中可以看到,父组件中的样式设置被覆盖:
h2 {
background-color: red;
}
:首先,我们发现两者h2选择器后面都没有加上[data-v-x],即结论1:
结论1:无论父子组件,不加scoped的style标签中的选择器不会增加[data-v-x]属性选择器。
同时,由于父组件的样式被覆盖,因此得出第二个结论:
结论2:对于同一个选择器,子组件不含scoped的style标签中的样式优先级高于父组件。
(二)加scoped的style样式
对于父组件的h3元素,起作用的是
h3[data-v-04c2046b] {
background-color: red;
}
对子组件的h3元素,生效的是
h3[data-v-10e5fd3c] {
background-color: blue;
}
我们发现,只有组件自身含scoped的style标签中对h3设置的样式生效。
这不难理解,写在含scoped的style标签中的选择器都会加上形如[data-v-04c2046b]这样的属性选择器后缀。虽然在父、子组件含scoped的style标签中都对h3样式进行了设置,但h3加上的是不同的data-v-x属性选择器后缀,因此相互不能匹配,彼此毫无影响。
因此,得出以下结论:
结论3:无论父子组件,加scoped的style标签中的选择器都会增加[data-v-x]属性选择器。
结论4:对于同一个选择器,父子组件含scoped的style标签中的样式互不影响。
(三)同一个组件,加或不加scoped
如果我们在子组件含scoped的style中增加:
h2 {
background-color: orange;
}
那么,最终效果如下:
现在,我们捋一捋为什么会是这个效果:
首先,来看子组件的h3,父组件含scoped的style对h3的设置不会影响子组件(结论4),那么子组件的h3将显示蓝色。对于父组件的h3,同样由结论4,显示红色。对于父组件的h2,由结论2显示蓝色,并且子组件含scoped的style中对h2的设置影响不到父组件。
对于子组件的h2,由结论2,本应显示蓝色,但是,子组件含scoped的style中对h2的设置将覆盖子组件不含scoped的style中对h2的设置,因此显示黄色。
由上,我们得出新的结论:
结论5:在同一个组件中,对于同一个选择器,含scoped的style中设置的样式优先级高于不含scoped的style中设置的样式。
这不难理解,含scoped的style中的选择器会加上特定的data-v-x属性选择器后缀,优先级将超过不带后缀的选择器。
五、小结
html篇:
1、某个组件自身的元素是否会加上data-v-x属性,看该组件是否有带scoped的style标签,而不论这个style标签中有无样式设置,写了什么样式。
2、若某个组件有带scoped的style标签,则该组件的根元素、组件自身的后代元素、子组件的根元素都会增加data-v-x属性。
3、子组件的根元素会受到父组件data-v-x属性影响,非根元素则始终不会。
CSS篇:
1、含scoped的样式:父子组件互不影响,原因是增加了属性选择器后缀,彼此不能匹配。
2、不含scoped的样式:父子组件相互影响,但子组件优先级高于父组件。
3、同一个组件:不含scoped和含scoped的样式,含scoped的优先级更高,原因也是含scoped的选择器增加了属性选择器后缀。
Vue.js中scoped引发的CSS作用域探讨的更多相关文章
- Vue.js中css的作用域
Vue.js中的css的作用域问题: 如果在vue组件下的style中定义样式,效果会作用于整个html页面,如果只想本组件的css样式只作用于本组件的话,在<style>标签里添加sco ...
- vue.js中的slot
vue.js 中的 slot 一.slot 的作用 调用组件的时候,对于数据,我们会用props将数据从父组件传至子组件.但是,如果从父组件到子组件,单纯是页面局部渲染的改变,slot会更合适. 二. ...
- vue.js中,input和textarea上的v-model指令到底做了什么?
v-model是 vue.js 中用于在表单表单元素上创建双向数据绑定,它的本质只是一个语法糖,在单向数据绑定的基础上,增加了监听用户输入事件并更新数据的功能: 对,它本质上只是一个语法糖,但到底是一 ...
- 实例分析Vue.js中 computed和methods不同机制
在vue.js中,有methods和computed两种方式来动态当作方法来用的 1.首先最明显的不同 就是调用的时候,methods要加上() 2.我们可以使用 methods 来替代 comput ...
- Vue.js中使用select选择下拉框
在Vue.js中使用select选择下拉框有两种方法: 第一种: Add.html: <select v-model="sysNotice.noticeType" id=&q ...
- vue.js 中双向绑定的实现---初级
1. 1 我们看到的变量,其实都不是独立的,它们都是windows对象上的属性 <!DOCTYPE html> <html lang="en"> <h ...
- 浅析Vue.js 中的条件渲染指令
1 应用于单个元素 Vue.js 中的条件渲染指令可以根据表达式的值,来决定在 DOM 中是渲染还是销毁元素或组件. html: <div id="app"> < ...
- vue.js 中 data, prop, computed, method,watch 介绍
vue.js 中 data, prop, computed, method,watch 介绍 data, prop, computed, method 的区别 类型 加载顺序 加载时间 写法 作用 备 ...
- angular.js和vue.js中实现函数去抖(debounce)
问题描述 搜索输入框中,只当用户停止输入后,才进行后续的操作,比如发起Http请求等. 学过电子电路的同学应该知道按键防抖.原理是一样的:就是说当调用动作n毫秒后,才会执行该动作,若在这n毫秒内又调用 ...
随机推荐
- 用人话告诉小白:什么是项目管理(例如Maven),什么是调试工具(即debugger),什么是编译(即compile)
项目管理 以java程序的项目管理软件Maven为例,java程序根据代码的不同需要不同的jar文件才能编译运行. 人物:两个程序员A和B 物品:一个java程序G,许多jar文件 场景:当A在自己电 ...
- Vulnhub DC-9靶机渗透
信息搜集 nmap -sP 192.168.146.0/24 #主机发现 nmap -A 192.168.146.147 #扫描端口等信息 22端口过滤,80端口开放,同样的从80端口入手. 不是现成 ...
- 使用 python 查看谁没有交作业
话说实验报告每天都要查人数,何不用程序实现 使用 python 查看谁没有交作业 version 1.0 程序嘛,肯定是可以改进的.使用该程序的前提是实验报告文件名中包含学号信息.将以上程序放在实验报 ...
- tf.nn.softmax 分类
tf.nn.softmax(logits,axis=None,name=None,dim=None) 参数: logits:一个非空的Tensor.必须是下列类型之一:half, float32,fl ...
- mysql几个操作数据库命令符下的常用命令
1.导出整个数据库 mysqldump -u用户名 -p密码 数据库名 > 导出的文件名 C:\Users\jack> mysqldump -uroot -pmysql sva_rec & ...
- CSS盒模型属性详细介绍
一.概述 CSS盒模型是定义元素周围的间隔.尺寸.外边距.边框以及文本内容和边框之间内边距的一组属性的集合. 示例代码: <!DOCTYPE html> <html lang=&qu ...
- 这届网友实在是太有才了!用python爬取15万条《我是余欢水》弹幕
年初时我们用数据解读了几部热度高,但评分差强人意的国产剧,而最近正午阳光带着两部新剧来了,<我是余欢水>和<清平乐>,截止到目前为止,这两部剧在豆瓣分别为7.5分和7.9分,算 ...
- 用python爬取之后发现果然如此,都说知乎的小姐姐漂亮
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http ...
- 无序map 记录一下
unordered_map<int ,int >mp; unordered_map是基于hash表实现的,查找元素的复杂度可以达到o(1),查找n个元素,复杂度为o(n). map是基于红 ...
- Docker-None & Host 网络
本节介绍None&Host网络. 1.前言 点击此处回到docker系列文章目录 前面我们介绍了bridge network,本小节继续介绍none和host.这两个比较简单,也不太常用.安装 ...