基于vue中的scoped坑点解说


Posted in Javascript onSeptember 04, 2020

今天在覆盖iview组件样式的时候发现一个问题,就是无法覆盖组件原有的样式,最后在github的issue中找到了答案:

不要使用scoped属性。于是我查找了下关于scoped的文章。

我们假设把这种组件叫做模块私有组件,其他的未加scoped的叫做模块一般组件。通过查看DOM结构发现:vue通过在DOM结构以及css样式上加唯一不重复的标记,以保证唯一,达到样式私有化模块化的目的。

代码如下:

//valChange.less(使用了嵌套规则)
#valueSlide{
  .bigSlider .ivu-slider-wrap{
    height: 6px;
  }
  .bigSlider .ivu-slider-bar {
    height: 6px;
  }
  .bigSlider .ivu-slider-button{
    width: 14px;
    height: 14px;
  } 
}

//html部分

<style lang="less" scoped>
  @import "./valChange.less";
</style>
<div class="valid-panel">
  <div class="containerBox">
    <div id="valueSlide" v-bind:style="validStyle">
      <Slider ></Slider>
    </div>
  </div>
</div>

也就是我们在style中使用scoped属性会出现下面的情况:

HTML部分:

基于vue中的scoped坑点解说

CSS部分:

基于vue中的scoped坑点解说

从上面的字可以看出,添加了scoped属性的组件,为了达到组件样式模块化,做了两个处理:

给HTML的DOM节点加一个不重复data属性(形如:data-v-19fca230)来表示他的唯一性

在每句css选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如[data-v-2311c06a])来私有化样式

那么问题来了:

对于当前组件下调用的其他组件,data属性只会添加到第一层HTML中:

基于vue中的scoped坑点解说

对于我们想覆盖的样式则无法起到作用:(在浏览器调试中手动添加 [data-v-19fca230] 属性后可以匹配)

基于vue中的scoped坑点解说

解决方案:

不使用scoped属性

总结一下scoped三条渲染规则:

给HTML的DOM节点加一个不重复data属性(形如:data-v-19fca230)来表示他的唯一性

在每句css选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如[data-v-19fca230])来私有化样式

如果组件内部包含有其他组件,只会给其他组件的最外层标签加上当前组件的data属性

问题补充:

1、如果不使用scoped如何解决样式全局污染?

推荐使用scoped推动组件私有化,文章所提到的不使用仅出现在已有UI库的样式覆盖上(当然人家用了scoped 那就很难办了)。

首先,解决组件样式全局污染,也就是我们在这里不使用scoped 覆盖了样式,那么我们在其他地方调用该组件就会被覆盖。那么我们在使用组件的时候对组件给一个类名 或者其他甄别属性(id),覆盖样式就针对该类名进行重写样式。

其次,解决其他样式全局污染,如果我们通过:

<style lang="less">
  @import "./test.less";
</style>

引进样式,那么不使用scoped ,"./test.less" 中的其他类名样式可能会污染全局,我这里用一个比较笨的方法处理:在模板中使用两次<style></style> 标签:

<style lang="less" scoped>
  @import "./test.less";
</style>
<style lang="less">
  //你的覆盖样式
</style>

这样既覆盖了样式,其他样式不会被覆盖到全局,效果代码我就补贴上来,感兴趣的同学可以自己试一试。(注意两个标签的顺序)。

官网 vue-loader 中提到每个vue模板中可以有多个<style></style>标签,所以上面的写法是没有问题的。

补充知识:Vue中的scoped及穿透方法 - - > scoped穿透

什么是scoped?

在vue文件中的style标签上,有一个特殊的属性:scoped。当一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,也就是说,该样式只能适用于当前组件元素。通过该属性,可以使得组件之间的样式不互相污染。如果一个项目中的所有style标签全部加上了scoped,相当于实现了样式的模块化。

scoped的实现原理

vue中的scoped属性的效果主要通过PostCSS转译实现,

如下是转译前的vue代码:

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

转译后:

<style>
.example[data-v-5558831a] {
 color: red;
}
</style>
<template>
 <div class="example" data-v-5558831a>hi</div>
</template>

即:PostCSS给一个组件中的所有dom添加了一个独一无二的动态属性,然后,给CSS选择器额外添加一个对应的属性选择器来选择该组件中dom,这种做法使得样式只作用于含有该属性的dom——组件内部DOM。

为什么需要穿透scoped?

scoped看起来很美,但是,在很多项目中,会出现这么一种情况,即:引用了第三方组件,需要在组件中局部修改第三方组件的样式,而又不想去除scoped属性造成组件之间的样式污染。此时只能通过特殊的方式,穿透scoped。

<style scoped>
  外层 >>> 第三方组件 {
    样式
  }
</style>

实际代码比如(我这里使用的是 elementui第三方组件库的组件名):

<style scoped>
/* .footerContainer是父级容器 .el-table--border td 是elementui自己封装的名字 */
.footerContainer >>> .el-table--border td {
 border-right: none;
}
.footerContainer .screen_configuration_el-table th {
 background-color: #eff2f7 !important;
 border-left: none !important;
 color: black !important;
}
.footerContainer >>> .el-table--border {
 border: 1px solid #ebeef5;
 border-left: none;
 border-right: none;
}
</style>

通过 >>> 可以使得在使用scoped属性的情况下,穿透scoped,修改其他组件的值。

还有一种方法就是引入外部 --> 全局 style css --> 曲线救国的方法

其实,还拥有一种曲线救国的方法,即在定义一个含有scoped属性的style标签之外,再定义一个不含有scoped属性的style标签,即在一个vue组件中定义一个全局的style标签,一个含有作用域的style标签:

<style>
/* global styles */
</style>
<style scoped>
/* local styles */
</style>

此时,你只需要将修改第三方样式的css写在第一个style中即可。

注意的地方:

如果使用 >>> scoped穿透选择器 就不能再style上面添加less sass scss 否则报错。

如下图:

基于vue中的scoped坑点解说

以上这篇基于vue中的scoped坑点解说就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
整理8个很棒的 jQuery 倒计时插件和教程
Dec 12 Javascript
JavaScript高级程序设计 阅读笔记(七) ECMAScript中的语句
Feb 27 Javascript
JavaScript中为什么null==0为false而null大于=0为true(个人研究)
Sep 16 Javascript
利用JavaScript实现新闻滚动效果(实例代码)
Nov 27 Javascript
js模仿hover的具体实现代码
Dec 30 Javascript
JavaScript事件委托的技术原理探讨示例
Apr 17 Javascript
JavaScript运行机制之事件循环(Event Loop)详解
Oct 10 Javascript
AngularJS快速入门
Apr 02 Javascript
Bootstrap所支持的表单控件实例详解
May 16 Javascript
使用Require.js封装原生js轮播图的实现代码
Jun 15 Javascript
JS实现数组去重方法总结(六种方法)
Jul 14 Javascript
利用JS制作万年历的方法
Aug 16 Javascript
VUE : vue-cli中去掉路由中的井号#操作
Sep 04 #Javascript
Vue利用localStorage本地缓存使页面刷新验证码不清零功能的实现
Sep 04 #Javascript
vue-cli3中配置alias和打包加hash值操作
Sep 04 #Javascript
vue深度监听(监听对象和数组的改变)与立即执行监听实例
Sep 04 #Javascript
Kettle中使用JavaScrip调用jar包对文件内容进行MD5加密的操作方法
Sep 04 #Javascript
解决vue中axios设置超时(超过5分钟)没反应的问题
Sep 04 #Javascript
在vue中axios设置timeout超时的操作
Sep 04 #Javascript
You might like
Yii2中使用asset压缩js,css文件的方法
2016/11/24 PHP
详解PHP安装mysql.so扩展的方法
2016/12/31 PHP
浅谈Laravel中的一个后期静态绑定
2017/08/11 PHP
PHP判断访客是否手机端(移动端浏览器)访问的方法总结【4种方法】
2019/03/27 PHP
PHP+mysql防止SQL注入的方法小结
2019/04/27 PHP
php 下 html5 XHR2 + FormData + File API 上传文件操作实例分析
2020/02/28 PHP
只需20行代码就可以写出CSS覆盖率测试脚本
2013/04/24 Javascript
js的Prototype属性解释及常用方法
2014/05/08 Javascript
Node.js中使用事件发射器模式实现事件绑定详解
2014/08/15 Javascript
JavaScript页面模板库handlebars的简单用法
2015/03/02 Javascript
跟我学习javascript的call(),apply(),bind()与回调
2015/11/16 Javascript
AngularJS  ng-repeat遍历输出的用法
2017/06/19 Javascript
Angular4 反向代理Details实践
2018/05/30 Javascript
解决webpack+Vue引入iView找不到字体文件的问题
2018/09/28 Javascript
Vue指令指令大全
2019/02/09 Javascript
详解写好JS条件语句的5条守则
2019/02/28 Javascript
在Vue项目中,防止页面被缩放和放大示例
2019/10/28 Javascript
Openlayers3实现车辆轨迹回放功能
2020/09/29 Javascript
[23:18]Spirit vs Liquid Supermajor小组赛A组 BO3 第二场 6.2
2018/06/03 DOTA
Python中用format函数格式化字符串的用法
2015/04/08 Python
Fabric 应用案例
2016/08/28 Python
python使用socket创建tcp服务器和客户端
2018/04/12 Python
python 爬虫 批量获取代理ip的实例代码
2018/05/22 Python
解决python 上传图片限制格式问题
2019/10/30 Python
如何在python中实现随机选择
2019/11/02 Python
链表面试题-一个链表的结点结构
2015/05/04 面试题
杭州信雅达系统.NET工程师面试试题
2015/02/08 面试题
2019年分享net面试的经历和题目
2016/08/07 面试题
解决python 输出到csv 出现多空行的情况
2021/03/24 Python
白酒业务员岗位职责
2013/12/27 职场文书
小学优秀辅导员事迹材料
2014/05/11 职场文书
拔河比赛口号
2014/06/10 职场文书
婚前协议书范本
2014/10/27 职场文书
2014年审计工作总结
2014/11/17 职场文书
2015年教师新年寄语
2014/12/08 职场文书
MySQL示例讲解数据库约束以及表的设计
2022/06/16 MySQL