基于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 相关文章推荐
通过ifame指向的页面高度调整iframe的高度
Oct 05 Javascript
精解window.setTimeout()&amp;window.setInterval()使用方式与参数传递问题!
Nov 23 Javascript
js cookies 常见网页木马挂马代码 24小时只加载一次
Apr 13 Javascript
jQuery学习3:操作元素属性和特性
Feb 07 Javascript
jQuery检测某个元素是否存在代码分享
Jul 09 Javascript
javaScript实现可缩放的显示区效果代码
Oct 26 Javascript
微信小程序 rpx 尺寸单位详细介绍
Oct 13 Javascript
js中获取 table节点各tr及td的内容简单实例
Oct 14 Javascript
jQuery插件ajaxFileUpload使用实例解析
Oct 19 Javascript
BootStrap 下拉菜单点击之后不会出现下拉菜单(下拉菜单不弹出)的解决方案
Dec 14 Javascript
react 父子组件之间通讯props
Sep 08 Javascript
Antd中单个DatePicker限定时间输入范围操作
Oct 29 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
PHP.MVC的模板标签系统(一)
2006/09/05 PHP
解析php如何将日志写进syslog
2013/06/28 PHP
PHP Curl出现403错误的解决办法
2014/05/29 PHP
ThinkPHP处理Ajax返回的方法
2014/11/22 PHP
laravel 5 实现模板主题功能
2015/03/02 PHP
PHP5.6新增加的可变函数参数用法分析
2017/08/25 PHP
js 小数取整的函数
2010/05/10 Javascript
js原型继承的两种方法对比介绍
2014/03/30 Javascript
jquery图片轮播插件仿支付宝2013版全屏图片幻灯片
2014/04/03 Javascript
JS实现两个大数(整数)相乘
2014/04/28 Javascript
Node.js中的模块机制学习笔记
2014/11/04 Javascript
轻松创建nodejs服务器(7):阻塞操作的实现
2014/12/18 NodeJs
使用Function.apply()的参数数组化来提高 JavaScript程序性能的技巧
2015/12/23 Javascript
AngularJS使用ngOption实现下拉列表的实例代码
2016/01/23 Javascript
JS正则表达式验证账号、手机号、电话和邮箱是否合法
2017/03/08 Javascript
angular实现图片懒加载实例代码
2017/06/08 Javascript
js中自定义react数据验证组件实例详解
2018/10/19 Javascript
Vue自定义组件的四种方式示例详解
2020/02/28 Javascript
Python字符串替换实例分析
2015/05/11 Python
如何安装并在pycharm使用selenium的方法
2020/04/30 Python
你可能不熟练的十个前端HTML5经典面试题
2018/07/03 HTML / CSS
捷克电器和DJ设备网上商店:Electronic-star
2017/07/18 全球购物
XD健身器材:Kevlar球、Crossfit健身球
2019/03/26 全球购物
size?荷兰官方网站:英国高级运动鞋精品店
2020/07/24 全球购物
门诊手术室工作制度
2014/01/30 职场文书
违反校纪校规检讨书
2014/02/15 职场文书
幼儿园父亲节活动方案
2014/03/11 职场文书
市场推广策划方案
2014/06/02 职场文书
家长反馈意见及建议
2015/06/03 职场文书
JavaScript中关于预编译、作用域链和闭包的理解
2021/03/31 Javascript
MySQL慢查询的坑
2021/04/28 MySQL
ORACLE查看当前账号的相关信息
2021/06/18 Oracle
python析构函数用法及注意事项
2021/06/22 Python
Python django中如何使用restful框架
2021/06/23 Python
使用canvas对video视频某一刻截图功能
2021/09/25 HTML / CSS
springboot如何接收application/x-www-form-urlencoded类型的请求
2021/11/02 Java/Android