基于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的eval JSON object问题
Nov 15 Javascript
浅谈javascript中字符串String与数组Array
Dec 31 Javascript
JavaScript函数基础详解
Feb 03 Javascript
vue如何使用 Slot 分发内容实例详解
Sep 05 Javascript
javascript按钮禁用和启用的效果实例代码
Oct 29 Javascript
详解bootstrap导航栏.nav与.navbar区别
Nov 23 Javascript
Vue.js 使用v-cloak后仍显示变量的解决方法
Nov 19 Javascript
vue实现歌手列表字母排序下拉滚动条侧栏排序实时更新
May 14 Javascript
详解jenkins自动化部署vue
May 14 Javascript
nuxt+axios实现打包后动态修改请求地址的方法
Apr 22 Javascript
原生js实现html手机端城市列表索引选择城市
Jun 24 Javascript
vue-以文件流-blob-的形式-下载-导出文件操作
Aug 07 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
索尼SONY ICF-7600A(W)电路分析
2021/03/01 无线电
再说下636单管机
2021/03/02 无线电
PHP无敌近乎加密方式!
2010/07/17 PHP
php explode函数实例代码
2012/02/27 PHP
无法在发生错误时创建会话,请检查 PHP 或网站服务器日志,并正确配置 PHP 安装(win+linux)
2012/05/05 PHP
基于php的微信公众平台开发入门实例
2015/04/15 PHP
UPUPW 更新 64 位 Apache 系列 PHP 7.0 正式版
2015/12/08 PHP
通过PHP简单实例介绍文件上传
2015/12/16 PHP
PHP的邮件群发系统phplist配置方法详细总结
2016/03/30 PHP
PHP查看SSL证书信息的方法
2016/09/22 PHP
Thinkphp 框架配置操作之配置加载与读取配置实例分析
2020/05/15 PHP
input输入框鼠标焦点提示信息
2015/03/17 Javascript
通过JS判断联网类型和连接状态的实现代码
2015/04/01 Javascript
javascript实现简单的省市区三级联动
2015/05/14 Javascript
JavaScript forEach()遍历函数使用及介绍
2015/07/08 Javascript
Jquery表单验证失败后不提交的解决方法
2016/10/18 Javascript
Javasript设计模式之链式调用详解
2018/04/26 Javascript
node.js自动上传ftp的脚本分享
2018/06/16 Javascript
vue 自定义指令自动获取文本框焦点的方法
2018/08/25 Javascript
vue.js+elementUI实现点击左右箭头切换头像功能(类似轮播图效果)
2019/09/05 Javascript
Layui数据表格之单元格编辑方式
2019/10/26 Javascript
在vue-cli创建的项目中使用sass操作
2020/08/10 Javascript
原生JavaScript实现随机点名表
2021/01/14 Javascript
[02:09]EHOME夺得首届辉夜杯冠军—现场颁奖仪式
2015/12/28 DOTA
基于scrapy实现的简单蜘蛛采集程序
2015/04/17 Python
python验证码识别教程之利用滴水算法分割图片
2018/06/05 Python
Python解释器及PyCharm工具安装过程
2020/02/26 Python
浅谈python锁与死锁问题
2020/08/14 Python
python使用布隆过滤器的实现示例
2020/08/20 Python
SQL数据库笔试题
2016/03/08 面试题
女方婚礼新郎答谢词
2014/01/11 职场文书
经典而简洁的婚礼主持词
2014/03/13 职场文书
专科应届毕业生求职信
2014/06/04 职场文书
文明上网主题班会
2015/08/14 职场文书
听课评课活动心得体会
2016/01/15 职场文书
简单且有用的Python数据分析和机器学习代码
2021/07/02 Python