为什么vue:deep、/deep/、>>>样式能穿透到子组件

在scoped标记的style中,只要涉及三方组件,那deep符号会经常被使用,用来修改外部组件的样式。

小试牛刀

不使用deep

要想修改三方组件样式,只能添加到scoped之外,弊端是污染了全局样式,后续可能出现样式冲突。

<style lang="less">
.container {
    .el-button {
        background: #777; 
    }
}

使用 /deep/ deprecated

 .container1 {
    /deep/ .el-button {
        background: #000; 
    }
}

使用 >>> deprecated

.container2 >>> .el-button {
    background: #222; 
}

当在vue3使用/deep/或者>>>::v-deep,console面板会打印警告信息:

the >>> and /deep/ combinators have been deprecated. Use :deep() instead.

由于/deep/或者>>>在less或者scss中存在兼容问题,所以不推荐使用了。

使用:deep

.container3 {
    :deep(.el-button) {
        background: #444; 
    }
}

那么问题来了,如果我按以下的方式嵌套deep,能生效吗?

.container4 {
    :deep(.el-button) {
        :deep(.el-icon) {
            color: #f00;
        }
    }
}

源码解析

/deep/或>>>会被编译为什么

编译后的代码为:

.no-deep .container1[data-v-f5dea59b] .el-button { background: #000; } 

源代码片段:

if (
  n.type === 'combinator' &&
  (n.value === '>>>' || n.value === '/deep/')
) {
  n.value = ' '
  n.spaces.before = n.spaces.after = ''
  warn(
    `the >>> and /deep/ combinators have been deprecated. ` +
      `Use :deep() instead.`,
  )
  return false
}

当vue编译样式时,先将样式解析为AST对象,例如deep/ .el-button会被解析为Selector对象,/deep/ .el-button解析后生成的Selector包含的字段:

{ type: 'combinator', value: '/deep/' } 

然后将n.value由/deep/替换为空 。所以转换出来的结果,.el-button直接变为.container下的子样式。

:deep会被编译为什么?

编译后的代码:

.no-deep .container3[data-v-f5dea59b] .el-button { background: #444; }

源代码片段:


      let last: selectorParser.Selector['nodes'][0] = n
      n.nodes[0].each(ss => {
        selector.insertAfter(last, ss)
        last = ss
      })
      
      const prev = selector.at(selector.index(n) - 1)
if (!prev || !isSpaceCombinator(prev)) {
selector.insertAfter(
  n,
  selectorParser.combinator({
    value: ' ',
  }),
)
}
selector.removeChild(n)

还是以.container4 :deep(.el-button)为例,当解析到:deep符号式,selector快照为

image.png

parent为.container4 :deep(.el-button),当前selector的type正好为伪类标识pseudo,nodes节点包含一个.el-button

经过递归遍历,生成的selector结构为.container4 :deep(.el-button).el-button

最后一行代码selector.removeChild(n)会将:deep(.el-button)移出,所以输出的最终样式为.container4 .el-button

如果样式为:deep(.el-button) { :deep(.el-icon) { color: #f00 } },当遍历.el-icon时找不到ancestor,所以直接将:deep(.el-icon)作为其icon时找不到ancestor,其结果为:

.no-deep .container4[data-v-f5dea59b] .el-button :deep(.el-icon) { color: #f00; }

因此,deep是不支持嵌套的。

结尾

插个广告,麻烦各位大佬为小弟开源项目标个⭐️,点点关注:

  1. react-native-mapa, react native地图组件库
  2. mapboxgl-syncto-any,三维地图双屏联动
阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=21455,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?