样式穿透
组件样式污染的核心原因,就是不加scoped的话,组件里的CSS选择器都是全局的,类名一重复就会互相覆盖。解决有两种办法,一是给组件最外层的顶级元素起唯一类名,靠人工保证不重复,不过一般不用;主流是给style加scoped,它的核心原理是编译时做两件事,一是给当前组件所有HTML元素,还有组件里引入的所有子组件(包括UI组件)的根标签(顶级元素),都自动加上唯一的data-v-xxx哈希属性,二是给当前组件的所有样式规则,也拼接这个哈希属性选择器,这样样式就只会匹配带相同哈希的元素,哈希几乎不会重复,就从根本上避免了样式污染。
也正因为scoped只给子组件的根标签加当前组件的哈希,子组件内部的非根元素,是它自己编译的,不会带当前组件的哈希,所以我们用带哈希的样式规则,根本匹配不到UI组件这类第三方组件的内部子元素,直接写样式就不生效。这时候就需要用样式穿透,Vue2.7及以后用:deep(),老版本的/deep/已经不兼容了,穿透的作用就是让编译器不对穿透后的选择器拼接哈希,这样样式就能直接匹配到UI组件内部的子元素,实现样式修改。
而且因为scoped会给子组件根标签加哈希,所以我们直接修改UI组件的根标签样式,不用穿透也能生效,这也是scoped的一个设计细节。