基于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 相关文章推荐
javascript代码加载优化方法
Jan 30 Javascript
JavaScript事件委托的技术原理探讨示例
Apr 17 Javascript
Bootstrap3.0学习教程之JS折叠插件
May 27 Javascript
Bootstrap编写一个同时适用于PC、平板、手机的登陆页面
Jun 30 Javascript
javascript类型系统——undefined和null全面了解
Jul 13 Javascript
使用Vue.js创建一个时间跟踪的单页应用
Nov 28 Javascript
js通过keyCode值判断单击键盘上某个键,然后触发指定的事件方法
Feb 19 Javascript
H5手机端多文件上传预览插件
Apr 21 Javascript
自适应布局meta标签中viewport、content、width、initial-scale、minimum-scale、maximum-scale总结
Aug 18 Javascript
Vue组件中slot的用法
Jan 30 Javascript
Layui给数据表格动态添加一行并跳转到添加行所在页的方法
Aug 20 Javascript
JS中如何优雅的使用async await详解
Oct 05 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
计数器详细设计
2006/10/09 PHP
php中目录,文件操作详谈
2007/03/19 PHP
php中0,null,empty,空,false,字符串关系的详细介绍
2013/06/20 PHP
php生成毫秒时间戳的实例讲解
2017/09/22 PHP
Laravel 集成 Geetest验证码的方法
2018/05/14 PHP
php实现将数据做成json的格式给前端使用
2018/08/21 PHP
PHP PDO数据库操作预处理与注意事项
2019/03/16 PHP
ThinkPHP3.2框架操作Redis的方法分析
2019/05/05 PHP
js change,propertychange,input事件小议
2011/12/20 Javascript
用js实现控件的隐藏及style.visibility的使用
2013/06/14 Javascript
JavaScript使用HTML5的window.postMessage实现跨域通信例子
2014/04/11 Javascript
jQuery和AngularJS的区别浅析
2015/01/29 Javascript
javaScript中push函数用法实例分析
2015/06/08 Javascript
jQuery 获取跨域XML(RSS)数据的相关总结分析
2016/05/18 Javascript
AngularJS 输入验证详解及实例代码
2016/07/28 Javascript
JSON对象 详解及实例代码
2016/10/18 Javascript
详解Angular2 之 结构型指令
2017/06/21 Javascript
jQuery实现获取table中鼠标click点击位置行号与列号的方法
2017/10/09 jQuery
利用Javascript获取选择文本所在的句子详解
2017/12/03 Javascript
详解搭建es6+devServer简单开发环境
2018/09/25 Javascript
实现高性能javascript的注意事项
2019/05/27 Javascript
JavaScript中var的重要性实例分析
2019/07/09 Javascript
Python的内存泄漏及gc模块的使用分析
2014/07/16 Python
零基础写python爬虫之抓取糗事百科代码分享
2014/11/06 Python
Python使用自带的ConfigParser模块读写ini配置文件
2016/06/26 Python
Python中对数组集进行按行打乱shuffle的方法
2018/11/08 Python
Python中查看变量的类型内存地址所占字节的大小
2019/06/26 Python
用python打印1~20的整数实例讲解
2019/07/01 Python
Django项目创建及管理实现流程详解
2020/10/13 Python
信访工作者先进事迹
2014/01/17 职场文书
运动会跳远加油稿
2014/02/20 职场文书
2014年开学第一课活动方案
2014/03/06 职场文书
会计专业自荐书
2014/07/08 职场文书
企业挂职心得体会
2014/09/10 职场文书
实习工作表现评语
2014/12/31 职场文书
苹果可能正在打击不进行更新的 App
2022/04/24 数码科技