4

因为疫情五一假期也不能出去玩,只好在家撸代码。

正好昨天排查了一个问题,今天记录一下。

问题

问题是这样的,有个页面它里面有两个组件 1活动组件、2搜索组件,然后活动组件里面有个评论留言的功能,测试同学发现组件切换之后评论被清空了
问题大体就这样。因为活动不是我做的,我只负责排查问题,所以我也是听别人的反馈来分析问题。

页面

感兴趣的朋友可以实际下载APP去看一下,VV音乐-首页轮播图-五一假期与美同行
如下,切换之后 UI 还在,只是记录数和评论没了

image.png

基础条件分析

  1. 单页面组件切换(不涉及到路由、或者页面通信乱七八糟的场景)
  2. 不存在页面被异常刷新情况(因为刷新就等于重新打开,重新打开是没有问题的。)
  3. 评论是公用的一个 js 实现,不是基于 Vue 的。(重点来了

    1. vue 讲究的是数据驱动视图,只要数据在,视图就ok
    2. js、jQuery 讲究的是 DOM,想插节点插节点,节点没了就没了。

常见问题排查

到这里问题已经比较清晰了,Vue 如何使用原生库。一般来说遇到的问题分为下面几个。

  1. 获取不到 DOM 节点。这里一般是 nextTick 的问题,因为你操作完数据之后,他并没有渲染完毕呢。
  2. 组件开发中获取 DOM 不方便,有可能出现重复。这里我们可以用 ref 来获取。
  3. 排序拖动等功能不生效。一般是看上去变了,但是数据不对。因为 jQuery库的理念就是 DOM 对了就是对了,但是在 Vue 中必须要数据对了,然后数据渲染到页面。所以处理方式一般是放弃修改 DOM,改为修改数据。

这个 Bug 还比较特殊,不是这里面的,但是也有关系(和 3 的问题类似)。接来下出道面试题吧

v-if 和 v-show 的区别

这面试题不陌生吧,想必大家也有答案。

v-if

v-if 根据表达式的值的来有条件地渲染元素。采用组件销毁、重建的方式。

如果一开始就是 false,那么这个组件不会被创建(生命周期钩子函数不会被调用)。

如果一开始是 true,然后改为 false,这个时候组件会被销毁(destory 等生命周期钩子函数都会执行)。之后如果再改为 true,那么会重新创建(created 等钩子函数会执行)。

v-show

v-show 根据表达式的值的来有条件地渲染元素。是通过设置元素的 display CSS 属性来实现渲染效果。

不管是 true 还是 false 都会渲染出组件。只不过为 falsedisplay:none

解决问题

基于上面的分析我们知道了,因为 v-if 导致组件被销毁,然后再次渲染的时候是根据 Vue 中的数据来渲染的,并没有 DOM 数据。

解决方案一:v-show

既然 v-show 不会销毁,那么我们可以缓存 v-show

这个方案的缺点

  1. 组件在一开始初始化的时候就全部被渲染了。会存在大量请求、无效数据打倒服务器。
  2. 因为他在一开始就渲染了,所以如果你没有加载完数据的话,存在报错的可能性。list && list.length 少不了这种代码的存在

解决方案二:切换之后再调用一次

既然 created 的时候是好的,那么我们切换之后再次调用一下初始化渲染不就可以了。

这个方案的缺点

  1. 因为存在二次渲染,jQuery 等插件一般都会监听事件。所以需要注意事件不能被多次触发。
  2. 还是因为上个问题,也要注意因为事件引用等问题导致的内存泄漏。

测试DEMO

https://www.lilnong.top/stati...

补一下 DEMO,可以看到一进去四个 input 都是有内容的。

切换之后 v-if 下面的input就有个丢值了。而 v-show 的不受影响。

增加 keep-alive 和组件测试

可以先在 keep-alive 组件中填入内容,然后切换,发现 v-if 的数据没有了
image.png

微信公众号:前端linong

欢迎大家关注我的公众号。有疑问也可以加我的微信前端交流群。
clipboard.png


linong
29.2k 声望9.5k 粉丝

Read-Search-Ask