更新:
后来发现是我自己做项目的时候出了点问题所以就导致在修改样式的时候以为所有的UI组件的样式在带有scope属性的style标签里都改不了,,,其实是可以直接给UI组件添加class类名,在style标签内用新类名修改样式去覆盖默认样式,必要的时候可以加上!important,,如果修改的是第三方UI组件深一层的子元素的样式,加上/deep/,v-deep,:::
我知道这篇文章写的不好~~以后继续加强
========================
不知道你们会不会遇到,反正我在做项目的时候遇到最多的一个问题就是,要修改样式,!!!而且要修改的是第三方UI组件的样式,我们知道第三方组件必须得全局修改才有有效,而且还得找准是修改哪个部分,一般会在浏览器控制台精准找到具体元素,并直接复制对应的类名。
但是,如果你使用了一个第三方组件,这个组件在多个地方重复使用,但你又要渲染不出同的样式效果,这就很为难了。
======================================
开始探索~
由于修改UI框架的样式必须是全局修改,不可以在style标签带有scoped属性的组件内修改,会失效。所以只能全局修改,那么,全局修改就会导致所有使用该组件的样式都一样。但是做项目做页面又会遇到同个组件样式不同。
而且!!!
这些封装好的组件就只有一两个标签,但是最终渲染出来时是有很多个标签并且大部分标签之间有很多嵌套,会因为需要准确修改到对应部分而遇到其他问题。
而且有些样式无法继承之类的,所以修改哪部分就必须找到哪部分,无法通过修改临近的元素或者父级元素、祖辈元素来修改想要的部分。
解决方案:
以下方案得根据实际需求使用,不是全都适用,仅供参考,是我自己遇到的总结出来的几个办法。
- 加ref属性,通过
this.$refs.
名称找到对应标签,得自己调试才能找准,通过console.log(this.$refs
)在控制台找其属性,可能在$refs
、$children
等等属性会找到对应的祖辈或子孙标签
注意:通过refs获取元素必须是在mounted生命周期,其获取的是真实地DOM元素,会跳过虚拟的DOM元素。
-
在vue文件里对应组件上直接加style内联样式(此方法适用于修改的就是本身元素或者这些内联样式可以被子孙元素继承)
-
我用过一个组件是vant UI框架的nav导航栏,刚好一个A页面的导航栏需要滚动,就有一个滚动类(导航栏长度很长,需要设置横向滚动),另一个B页面不需要滚动,就没有滚动类(导航栏长度比较短)
假设:
// A页面:
<nav class="van-tabs__wrap van-tabs__wrap--scrollable" ></nav>
// B页面:
<nav class="van-tabs__wrap" ></nav>
// 全局样式
.van-tabs__wrap{
...... (A、B页面会应用)
}
.van-tabs__wrap.van-tabs__wrap--scrollable{
......(A页面应用,就近原则,A页面最终应用这个样式)
}
-
像第三点说的一个有滚动类一个是没有滚动类,那如果遇到其他组件呢,又不像第三点,,,我试过一个是通过动态删除一个不需要的类嘻嘻嘻,这样就能让他们又可以想第三点一样了。至于怎么删掉呢
自己去调试 -
还有一种情况是表单标签!因为表单标签可以有name属性,所以可以通过name属性来区分它们。
比如(假设用的是第三方组件):
第三方组件的特点就是相同的组件类名都一样
私有组件里的结构:
<input name="username" class=“van-flied_control” type="text">
<input name="email" class=“van-flied_control” type="text">
// 全局样式文件里:
.van-flied_control['usernname']{
......
}
.van-flied_control['email']{
......
}
-
其实,如果你直接在A私有组件里直接通过js去修改,表面上好像真的有效修改了该组件的样式,其实,在js里面修改的样式也是全局的!!!最后其实也会被全局应用,那为什么有一些B、C等组件好像就没有被覆盖,这其实也得看你在项目里面怎么修改样式了,可能因为B、C组件的样式权重高、或者你也通过内联方式修改了样式等等问题就刚好B、C组件覆盖失效,所以你就以为刚刚通过js在A修改的样式真的只应用在A里(假象哈哈哈)。反正我在这个修改样式上用了很多办法,想了很多法子,遇到很多坑,调试了很多次~~~~
只有在带scoped属性的style标签内才是私有的。 -
后来!!!我又想到办法去解决第七种的问题,也一样用的是js修改!
方法就是:结合路由~
(1)反正跳转到其他路由,就修改样式去覆盖前面路由的,记得要修改完全哦,我图片里的home路由修改.van-tabs_line类的样式为什么比follow少了一条,是因为我home把它修改成颜色为#fff,在我的项目里他变成了白色也就是看不见了所以我就没修改宽度。反正你根据你自己实际需求去改
(2)为什么在监听路由变化也要调用那个修改样式的方法呢,可能你会觉得在mounted里面就足够了呀,其实是因为我这个项目里,home和follow路由里面还有子路由,因为自己项目的设计,那个带.van-tabs__line和.van-tabs__wrap的元素是父组件的,所以切换子路由的时候,这个元素是不需要重新渲染的,因为不需要重新渲染所以mounted内的就不会再执行,那可不行啦,你不执行,样式还是会有问题的。所以要通过watch监听$route路由的变化来修改样式。其实这个是我项目截取的一段,你可能会听起来懵懵的~ 反正你就是根据你自己项目的实际需求去改就好了,我就是给你提供下思路而已~
看红色框的内容就可以了~
-
注意:建议在mounted内修改样式时在对应样式外加个定时器,因为会存在页面未完全渲染完毕就获取元素,所以导致修改失败。定时器的作用就是!!!
只要遇到定时器就会把定时器放到代码最下面,最后再执行,而不是去等待。即使时间为0;(我之前遇到一个笔试题就是有涉及到定时器) -
有一些通过以上方式修改后,还是无效的话,可能加个
!important
就可以有效覆盖。 -
其实也可以通过不加scoped属性,而给每个组件的根元素
添加 id
来区分不同的组件,既实现了类似scoped的私有效果,也方便第三方组件样式的修改。
但是组件内的样式最好是嵌套的,才可以实现私有化。也可以每个子孙元素的选择器名称最前面加上根元素id选择器名称。
less 和 sass (css预处理器语言)就可以嵌套样式
// 第一种
<style lang="less">
#根元素id名称{
子孙元素选择器名称{}
......
}
// 第二种
<style lang="less">
#根元素id名称 子孙元素选择器名称{
......
}
</style>
</style>
- 阐述的有点乱,但能够给你提供灵感就好啦~~~以后有新的想法也会更新~希望有更好的修改方法出现