/deep/ 在 Vue2 样式中的问题。
太长不看:
不要在 Vue SFC 以外的地方使用/deep/
。对于 Vue3 ,请使用最新的:deep()
伪类选择器。
什么是/deep/
/deep/
是 Vue2 中一个重要的样式选择器,可以用于选择封装好的组件内部的样式。
如果直接在 Vue 组件上设置 class 属性,该属性只附加于子组件的最外层 DOM ,无法深入选择。
Vue 在编译模板代码时,会将/deep/
动态替换成[data-xxx-xxx]
的形式,变成一个属性选择器,这个属性选择器是动态生成且唯一的,能够有效增加权重,并实现精确选择。
/deep/
的由来
/deep/
其实曾经是进入过提案的选择器,被称作 Shadow boundary-piercing combinators ,用来选择 web-components 中 shadow-root 里的样式。直到 2017 年才从 chrome 中移除。移除之后也不是完全没用了,而是退化成后代选择器(也就是说,还能被浏览器解析)。
考虑到 Vue2 设计发展的年代,引入 boundary-piercing 这个概念,并模仿选择器也是很合理的。Vue3 就完全拿掉了SFC CSS Features | Vue.js (vuejs.org)。
/deep/
失效的原因
Vue 能够编译/deep/
选择器是因为 vue-loader 的工作:CSS 作用域 · vue-loader (vuejs.org)
而对于 less 而言,只会将这个选择器直接原样输出。对于大部分 Webpack 项目,less 文件一般通过 less-loader 加载,lessc 编译,传递给 css-loader,最后经由 style-loader 在 html 文件中添加 style 标签。style-loader - npm (npmjs.com)
在 89 版本以前的 chrome,可以识别 xxx /deep/ ooo,并解析为后代选择器(空格)。但 89 版本之后就完全不能解析这个选择器了,也就呈现出完全无效的情况。
总结
- Vue SFC 中
/deep/
没有问题,放心使用。反之,单独的 less/sass/css 文件坚决不要用; - Vue2 项目尽早转向 Vue3 项目,和历史包袱说再见。