Vue中动态class覆盖原生class的问题

这一个小伙伴发来的bug

现在的问题是

这个下拉的菜单有时候关不上

现在是正常

但是呢当我切换一个界面

我们再回来

大概就关不掉了

点击空白处也不好使

只能去点击上面这个菜单

碰到这种问题呢

我们首先肯定是想到去看一下

他代码的逻辑

是怎么写的

但是呢我去看了一圈竟然发现

他连一个click事件都没有写

大家看

只是呢我发现他有一个这样的属性

还有这个

后来我搜了一下哈

这个啊就是bootstrap的一个属性

所以就意味着它现在啊

这个展开和收起的效果

都是由bootstrap来管理的

所以刚开始看到这呢线索一下就断了

就无从下手了

后来呢我就想了个办法

既然他正常的情况下

可以点击空白处去收起

说明他肯定有

点击事件放在全局了

所以呢我们可以这样选中body

然后在这选event list

然后展开click

大家看有这么多click

然后呢我们先把它展开

我们就一个一个的移除

看看把哪个移除掉之后

他这个点击空白处他就不好使了

比如说我随便移除一个

大家看它还能关闭

我再把它打开

我就移除第一个

大家看这回就没有了

说明啊刚才我移除的那个第一个

就是来管理这个菜单关闭的

我们再刷新一下 (目的是把移除的第一个事件还原回来)

好然后我们把它打开

我们直接点进去第一个

点进去之后呢

我发现它是一个公用的时间绑定的

那我们就在这apply上面打个断点

然后点空白处

走到这之后呢

把断点关掉

单步跳入

我们看走到哪个方法里

然后呢

我们来看一下他这个方法是怎么走的

注意走到这之后呢

他有一个循环

注意他现在循环的这个数组啊open togens

是有直的大家看

然后呢后边我们先不看了哈

我们直接放行

我们把这个

bug复现出来

先点别的地方

然后再回来

好现在就关不掉了对吧

然后我们还是在这打断点

我们再点一下空白处

大家看这个open tons就没有数据了

这个数据

所以他就不会走里边了

所以呢现在就有一点线索了

在有bug的情况下

这个变量是没有数据的

那为什么他没有数据呢

我们重新来走一下这个代码

我们现在放行一下

看在这为什么没找到对吧

大家看走到这了我们单步跳入

走进去之后呢

我们会发现其实他就是在调query selector

我们右键啊把它复制出来copy string contents

然后我们在控制台自己写一个

document.querySelectorAll

然后呢把刚才这个selector拿过来

大概是没有的

那我们再把它的范围扩大一点

我们去掉一些选择

只留一个这个大概就有了

然后呢再加上一些

我就只去掉show吧

大家看 就有了

加上show呢

就没了

也就是说在关不掉的情况下

应该有这么一个元素是有.show的

但是它没有了

哪个元素呢

我们来看这个a标签

大家看正常是没有展开的时候没有

但是我们把它展开的时候呢

它是有一个show 的样式的

这个样式其实就是bootstrap

直接来操作到我们节点来放上去的

比如说当我们展开的时候呢

bootstrap会给这个a标签加一个show

然后点空白的地方呢

它会通过这个.show(配合其他selector拼接)来找到这个a标签

然后去进行关闭操作

但是呢当我们切换页面的时候

注意啊我们切换再回来

大家看现在这个菜单是打开的

但是这个show已经没了

那为什么会这样呢

看到这啊

对vue比较熟的小伙伴可能会猜到

它这个a标签啊有一个动态的class

这里边的条件如果发生变化了

will就会把整个这个

class列表重新渲染

我们来看这个例子

这个例子里面就一个span标签

然后一个切换样式的按钮

代码呢也很简单就是这样

一个span标签

然后呢它有一个静态的样式

还有一个动态的样式

这个动态呢就是一个true和false

然后通过这个按钮来切换它的true/false

我们来看一下啊

现在呢它只有一个static

然后点按钮再看多了一个动态

再点呢动态就没了对吧

然后注意我在这手动加一个样式叫red

大家看它就有红色背景了

但是呢

这个时候我再点按钮切换的时候

注意这个red就丢了

大家看

原因就是啊

我们直接操作到dom节点

加的这个样式

没有被vue记录下来

所以当他再次重新渲染的时候呢

这个red样式就丢了

回到这个呢他也是这样的

所以呢解决这个小伙伴的bug呀

我研究了一下有两个方案

第一个方案就比较快

就是我们呀

无论如何都给他加一个.show

我看了一下

bootstrap没有对这个(.nav-link的).show

进行页面样式的声明

也就是说:这个show

只是用于js层面的一个判断(标识)

它没有任何样式的声明

所以呢我们给它加上也不会影响样式

大家看我们再来试一下

可以收起

切换回来也没有问题了

因为回来的时候默认他有个show

然后呢bootstrap就可以

找到这个元素顺利的把它关掉了

这是第一种方案

第二种方案呢就是啊

我看了一下他用的这个bootstrap啊

就是原声的这个Boosttrap

其实呢Boostrap是有vue版的Boostrap的

所以呢最理想的是啊

我们采用vue版的bootstrap

然后呢他想用的什么组件

包括这个下拉的组件这里边他都有

Dropdown

它叫b-dropdown

所以呢

如果我们采用这个vue版的bootstrap

我相信这个问题也能得到解决

而且呢应该说会解决的更彻底

最后更新于