基于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 相关文章推荐
js动态调用css属性的小规律及实例说明
Dec 28 Javascript
JS中使用Array函数shift和pop创建可忽略参数的例子
May 28 Javascript
javascript面向对象之对象的深入理解
Jan 13 Javascript
JavaScript数组和循环详解
Apr 27 Javascript
在HTML中插入JavaScript代码的示例
Jun 03 Javascript
JavaScript编写简单的计算器
Nov 25 Javascript
一步一步封装自己的HtmlHelper组件BootstrapHelper(三)
Sep 14 Javascript
requirejs按需加载angularjs文件实例
Jun 08 Javascript
详解Vue-cli3 项目在安卓低版本系统和IE上白屏问题解决
Apr 14 Javascript
Async/Await替代Promise的6个理由
Jun 15 Javascript
JavaScript实现拖拽功能
Feb 11 Javascript
Vue实现PC端靠边悬浮球的代码
May 09 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
织梦模板标记简介
2007/03/11 PHP
基于PHP5魔术常量与魔术方法的详解
2013/06/13 PHP
PHP echo,print,printf,sprintf函数之间的区别与用法详解
2013/11/27 PHP
详解PHP中mb_strpos的使用
2018/02/04 PHP
JavaScript的parseInt 进制问题
2009/05/07 Javascript
jquery获取元素索引值index()示例
2014/02/13 Javascript
运用jQuery定时器的原理实现banner图片切换
2014/10/22 Javascript
jQuery使用fadein方法实现渐出效果实例
2015/03/27 Javascript
JavaScript中实现map功能代码分享
2015/06/11 Javascript
jQuery实现简单的点赞效果
2020/05/29 Javascript
JavaScript中闭包的写法和作用详解
2016/06/29 Javascript
Angular中实现树形结构视图实例代码
2017/05/05 Javascript
Node.js 8 中的重要新特性
2017/06/28 Javascript
Vue 中对图片地址进行拼接的方法
2018/09/03 Javascript
vue中axios请求的封装实例代码
2019/03/23 Javascript
vue递归组件实战之简单树形控件实例代码
2019/08/27 Javascript
如何基于javascript实现贪吃蛇游戏
2020/02/09 Javascript
基于Vue+Webpack拆分路由文件实现管理
2020/11/16 Javascript
全面了解python字符串和字典
2016/07/07 Python
详解Python异常处理中的Finally else的功能
2017/12/29 Python
python中的随机函数random的用法示例
2018/01/27 Python
matplotlib subplots 调整子图间矩的实例
2018/05/25 Python
解决Tensorflow使用pip安装后没有model目录的问题
2018/06/13 Python
Python基于递归算法求最小公倍数和最大公约数示例
2018/07/27 Python
解决python3 Pycharm上连接数据库时报错的问题
2018/12/03 Python
python实现桌面气泡提示功能
2019/07/29 Python
Django REST Framework 分页(Pagination)详解
2020/11/30 Python
跨域修改iframe页面内容详解
2019/10/31 HTML / CSS
DC Shoes俄罗斯官网:美国滑板鞋和服饰品牌
2020/08/19 全球购物
网络公司美工设计工作个人的自我评价
2013/11/03 职场文书
应届毕业生个人求职自荐信
2014/01/06 职场文书
车间机修工岗位职责
2014/02/28 职场文书
2014年最新学习全国两会精神心得
2014/03/17 职场文书
2015年财务经理工作总结
2015/05/13 职场文书
2016年暑期见闻作文
2015/11/25 职场文书
15个值得收藏的JavaScript函数
2021/09/15 Javascript