vue 子组件样式覆盖问题 scoped deep

前言:

在项目开发过程中,经常会遇到需要在父组件内部覆盖子组件样式的场景,这种场景在使用第三方库开发时更为常见。如何处理好全局样式和局部样式对于长期更新维护的项目来说是非常重要的。

scoped分析:

对于SPA项目,只有一个页面,页面内容被拆分成了一个个组件,组件加载完成后,组件的样式也都加载在同一个页面内,所以这些组件的样式都可以看成全局样式,对其他组件都有效,要避免当前组件的样式对其他组件产生污染,就要把每个组件的样式独立开。

如果style添加scoped,当前组件所有标签都会添加一个data-v-hash的属性,hash值每个组件都不同

vue 子组件样式覆盖问题 scoped deep_第1张图片

css编译后,会在最后一级选择器后加一个属性选择器

vue 子组件样式覆盖问题 scoped deep_第2张图片

这样每个组件都有唯一的属性选择器,就可以避免对其他组件产生影响

deep分析:

deep是常用来样式穿透,覆盖子组件加了scoped的样式或者第三方组件的样式。

vue 子组件样式覆盖问题 scoped deep_第3张图片

上图中span为子组件,父组件样式加了scoped,子组件只有最外层元素添加了父组件的data-v-hash属性,如果只是需改最外层元素样式,不需要加deep,但是如果修改内部元素,直接使用类选择器是无效的。比如通过父元素类型panel修改类名ant-input的元素,最终的样式被编译为 

子组件内部元素没有data-v-hash属性,所以样式不生效。

如果使用deep:

最终样式会被编译为:

属性选择器只加在deep前的元素上,因此会影响子组件样式。 

使用总结:

1、所有组件必须加scoped

        如果没有加scoped? 打开一个界面突然发现A组件样式被其他组件权重更高的样式覆盖了,然后为了让A原本的样式生效,给A原本的样式加个更大的权重,接着又发现在B组件内部原本要覆盖A组件的一些样式,因为A组件样式权重变大而失效了。如果组件层级很深,子组件的最终样式来源可能要向上翻十八辈祖宗啊,真一点不夸张。

        当然也有同学喜欢不加scoped,样式最外层加个唯一的id选择器来避免对其他组件禅城影响,这样也可以达到效果,而且修改子组件样式的话会比较简单,但是自定义的id没办法全局管理,难以避免id重复的问题。

2、父组件覆盖子组件使用deep

        第三方库一般会有全局样式覆盖,不过是针对全局的样式,局部样式还是不要放在common.less里。使用deep需要注意两点:

        1、给组件额外加个类名,使用当前组件自定义类型进行样式覆盖

比如父元素为.father,如果覆盖ant design vue 的select组件,select组件最外层元素为.ant-select,我们直接使用.father /deep/ .ant-select { color: wisdom } 这样是可以生效的,但是对于.father下的所有子组件以及子孙后代组件,只要使用了select组件,{ color: wisdom }这个样式都是有效的,这样显然也不合理,为了不影响后代的组件,给select加个跟当前业务相关的类名,使用自定义类名覆盖样式,如.father /deep/ .father-child-select { ... }。PS:我也尝试过使用>选择器加/deep/一起使用,奈何无效。

        2、/deep/ 嵌套使用在新版chrome浏览器样式会失效,避免嵌套使用

以前嵌套使用是没问题的,后来遇到某个版本样式失效了

 PS:

        样式覆盖只要选择器匹配上了,其他无非是权重问题,组件慎用!important

你可能感兴趣的:(css,vue.js,前端,css)