理解vue中less的scoped和/deep/工作原理

  • scoped
  • /deep/
  • 实战
  • 总结

scoped

vue项目一般是单页面、多组件,整个项目共用一个css样式表,有时候我们在写组件的过程中并不希望组件的样式污染全局作用域(毕竟不同组件之间重名的class很正常),因此我们会在组件的样式标签上加上scoped,例如下面这个最基本vue组件框架:

<template>
...
</template><script>
import ...
export defualt {data(){...}...
}
</script><style lang="less" scoped>
...
</style>

那么这个scoped是什么意思呢?其实就是给每条样式的 最后面 加上一个属性选择器[哈希值],这个哈希值在项目里全局唯一,代表了当前这个组件。例如当前组件用到了 haha.vue , 那么在打包的时候就会编译出一个data-v-5cfc4ef6来唯一代表这个组件。注意一个vue文件里可能有多个哈希值,因为一个组件里还可能嵌套了其他组件。

废话不多说,直接看scoped是怎么工作的。例如:

<style lang="less" scoped>.a{.b{background-color:#bfa}}
</style>

则打包编译后这个属性会变成这样:

 .a .b[data-v-5cfc4ef6]

注意了,.a和.b之间有空格,表示父子元素;.b和[data-v-5cfc4ef6]无空格,表示并集。那么这条css语句什么意思呢?class为a的元素下的 class为b且具有data-v-5cfc4ef6属性的元素。这样就做到了css样式只针对本组件(哈希值为data-v-5cfc4ef6)的元素

/deep/

那么deep是什么呢?博主找遍全网,找到的信息大意都是:“能够让被scoped限制住的样式属性穿透到子组件”,简直tm在坑爹!这话是不错,但是说了等于没说:为什么平时写项目,同样都是引用自组件,有些地方用/deep/有些地方不用呢?经过我自己的摸索,发现/deep/的工作规律是这样的:
/deep/ === [哈希值]
啥意思呢?还是刚才那个例子,加一个deep:

<style lang="less" scoped>.a{/deep/.b{background-color:#bfa}}
</style>

那么编译后的结果就会是:

 .a[data-v-5cfc4ef6] .b

注意这个.a[data-v-5cfc4ef6]之间没有空格,表示并集;.a[data-v-5cfc4ef6].b之间是有空格的,表示子元素。
结合less的嵌套语法,我们发现是这样的:
/deep/某个属性前,表示父元素要拥有 哈希值这个属性,而如果没有写/deep/,这个 哈希值是会被scoped到叶子元素上的(最深的子元素,就像上一个例子所演示的那样)。
再举个例子:

/deep/div

会被打包编译成

[data-v-5cfc4ef6] div

注意有空格,表示父元素有 哈希值这个属性的所有div元素,也就是这个组件下的所有div元素了。

实战

有同学会问了,既然scoped会自己帮我们把哈希值放在叶子元素上,为什么还要自己写/deep/来调整哈希值的位置呢?我曾经也有这样的疑问,直到我用了antd…
话不多说,直接看代码:

<template><div class="user-detail-wrap"><a-card :bodyStyle="{padding:'20px'}"><a-row:gutter="8"><a-col :sm="5" :xs="5" class="title">编辑角色<a @click="goBack"><img:src="returnIcon"style="height: 18px" /></a></a-col><a-col :sm="3" :xs="3" style="float:right;"><a-button type="primary" style="width:80px;float:right;" v-action:save @click="goSave">保存</a-button><a-modal:visible="confirmVisible"@cancel="handleCancel"><p class="title"><img :src="warningIcon" alt="" class="warning-icon"><span class="confirm-title">{{ confirmTitle }}</span></p><p class='confirm-text'>{{ confirmText }}</p><template slot="footer"><a-button key="back" @click="handleCancel">取消</a-button><a-button key="submit" type="primary" :loading="confirmLoading" @click="handleConfirm">修改</a-button></template></a-modal></a-col></a-row></a-card><a-card :bodyStyle="{padding:'20px'}" class="table-card"><a-row:gutter="8"><a-col :sm="5" :xs="5" class="title">基础信息</a-col></a-row><a-card-gridstyle="width:25%;padding:10px"v-for="(record, index) in roleInfoColums":key="index">{{ record.title }}: {{ roleInfo[record.dataIndex] }}</a-card-grid></a-card><a-card :bodyStyle="{padding:'20px'}" class="table-card"><a-row:gutter="8"><a-col :sm="5" :xs="5" class="title">权限信息</a-col></a-row><permission-tree:treeData="treeData":disableAll="false"@onSelectChange="onSelectChange"></permission-tree></a-card></div>
</template>

打包之后呈现出的部分DOM树是这样的:

可以看到,父元素ant-modal-root有哈希值,而子元素ant-modal-footer却没有,但是ant-modal-footer的两个button自元素又有哈希值了(可能是因为ant-modal-footer是我插入的另一个template slot的根元素)

 <template slot="footer"><a-button key="back" @click="handleCancel">取消</a-button><a-button key="submit" type="primary" :loading="confirmLoading" @click="handleConfirm">修改</a-button></template>

这时候,如果不写deep,而是让scoped自己来的话

.ant-modal-root {.ant-modal-footer {border-top: 0;overflow: hidden;padding: 32px;padding-top:18px;}
}

就会编译出这样的css样式:

 .ant-modal-root .ant-modal-footer[data-v-5cfc4ef6]

可是我tm上哪里找有data-v-5cfc4ef6属性的ant-modal-footer…

写上deep:

.ant-modal-root {/deep/.ant-modal-footer {border-top: 0;overflow: hidden;padding: 32px;padding-top:18px;}
}

就编译成了:

 .ant-modal-root[data-v-5cfc4ef6] .ant-modal-footer

这下就能选中了。

总结

用到第三方组件的时候,经常会自己定义插槽slot来替换原组件里的内容,这时候就很容易遇到要手动用/deep/的问题。遇到这类问题的时候,不要盲目地用!important来提高优先级(这样不管用),甚至不加scoped写样式,或者直接通过import .less 引入外部样式来污染全局了(这样会有副作用)

理解vue中less的scoped和/deep/工作原理相关推荐

  1. vue中style的scoped属性这样用,修改第三方组件iview 或 element 样式

    vue中style的scoped属性这样用,修改第三方组件iview 或 element 样式 文章目录 vue中style的scoped属性这样用,修改第三方组件iview 或 element 样式 ...

  2. vue中style的scoped属性的设计方式

    vue中style的scoped属性这里是怎实现的呢? scoped三条渲染规则 给HTML的DOM节点加一个不重复data属性(形如:data-v-2311c06a)来表示他的唯一性 在每句css选 ...

  3. [Vue][面试]你怎么理解vue中的diff算法?

    你怎么理解vue中的diff算法? #####源码分析1:必要性,lifecycle.js–mountComponent() vue中一个组件一个watcher实例,而组件中可能存在很多个data中的 ...

  4. 深入理解vue中的slot与slot-scope (简单易懂)

    走在前端的大道上 插槽,也就是slot,是组件的一块HTML模板,这块模板显示不显示.以及怎样显示由父组件来决定. 实际上,一个slot最核心的两个问题在这里就点出来了,是显示不显示和怎样显示. 由于 ...

  5. 前端面试 vue生命周期钩子是如何实现的?理解vue中模板编译原理?

    生命周期钩子在内部会被vue维护成一个数组(vue 内部有一个方法mergeOption)和全局的生命周期合并最终转换成数组,当执行到具体流程时会执行钩子(发布订阅模式),callHook来实现调用. ...

  6. 如何理解vue中 同步异步

    如何理解vue中 同步异步 同步异步 , 举个例子来说,一家餐厅吧来了5个客人,同步的意思就是说,来第一个点菜,点了个鱼,好, 厨师去捉鱼杀鱼,过了半小时鱼好了给第一位客人,开始下位一位客人,就这样一 ...

  7. 理解vue中的slot-scope=“scope“

    理解vue中的slot-scope="scope" slot是插槽,slot-scope="scope"相当于一行的数据 <el-table-column ...

  8. 探讨Vue 数据监测原理-第五节-展开介绍 Vue中监测-【数组】数据的原理

    文章目录 探讨一下Vue 数据监测的原理 本次探讨共的第五个章节 第五节:展开介绍 Vue中监测-[数组]数据的原理 1. 案例 1.1. 页面案例 2. 数组形式|对象形式爱好的区别 2.1. 页面 ...

  9. CPU CACHE中的VIPT与PIPT的工作原理

    转自CPU CACHE中的VIPT与PIPT的工作原理_Linux与SoC的博客-CSDN博客 启动信息描述 内核启动过程中有如下打印信息: CPU: PIPT / VIPT nonaliasing ...

最新文章

  1. 【SQL Server】系统学习之一:表表达式
  2. 从“诺奖级”成果到“非主观造假”,时隔6年,韩春雨带着原一作,再发高分文章!...
  3. linux(ubuntu) 查看系统设备信息 命令
  4. 【Python】Pyecharts数据可视化模块练习
  5. uwsgi指定python路径_uWsgi服务器(2)--安装配置
  6. 高起专计算机应用基础试题及答案,重庆大学网络教育高起专计算机应用基础入学考试模拟题及答案(二)...
  7. 吉林大学不如温州大学,泰晤士最新世界大学排名引发争议
  8. 中科院回应木兰语言造假:当事人已停职;中国软件业务收入百强:华为蝉联十八冠;Ionic 5.0.0-beta.5 发布|极客头条...
  9. 你们都用什么反编译工具?
  10. (转载)Web各大服务器区分(整理)
  11. html英文书籍推荐,Html英文
  12. 基于WizFi220的Cosmo WiFi扩展板
  13. 使用Raspberry Pi搭建迅雷离线下载机
  14. iOS常见崩溃以及总结
  15. 小程序中自定义组件、父子传值的具体步骤(秒懂)
  16. flex android开发中关于请求报文技术操作问题
  17. 纯css画一个月亮的天气图标
  18. 物联网智慧物流平台开发
  19. scala特质 对比java的接口 使用方法
  20. curl命令发送Post请求

热门文章

  1. 神州数码DCRS试题题目合集
  2. Linux中使用echo修改用户密码
  3. 读《断舍离》部分摘录
  4. go test, go bench go examples
  5. Eric6启动时“无法定位序数4540于动态链接库LIBEAY32.dll”的错误
  6. 大数据:塑造国家竞争新优势
  7. 用一张船票,去往5G未来:华为 Mate20 X(5G)的降临故事
  8. 历时六年,东安汽发实现自动变速器领域新突破
  9. 15 款面向内容创作者的 AI 工具
  10. SQL常用语法网络整理版本