因为疫情五一假期也不能出去玩,只好在家撸代码。
正好昨天排查了一个问题,今天记录一下。
问题
问题是这样的,有个页面它里面有两个组件 1活动组件、2搜索组件,然后活动组件里面有个评论留言的功能,测试同学发现组件切换之后评论被清空了。
问题大体就这样。因为活动不是我做的,我只负责排查问题,所以我也是听别人的反馈来分析问题。
页面
感兴趣的朋友可以实际下载APP去看一下,VV音乐-首页轮播图-五一假期与美同行
如下,切换之后 UI 还在,只是记录数和评论没了。
基础条件分析
- 单页面组件切换(不涉及到路由、或者页面通信乱七八糟的场景)
- 不存在页面被异常刷新情况(因为刷新就等于重新打开,重新打开是没有问题的。)
-
评论是公用的一个 js 实现,不是基于 Vue 的。(重点来了)
- vue 讲究的是数据驱动视图,只要数据在,视图就ok
- js、jQuery 讲究的是 DOM,想插节点插节点,节点没了就没了。
常见问题排查
到这里问题已经比较清晰了,Vue 如何使用原生库。一般来说遇到的问题分为下面几个。
- 获取不到 DOM 节点。这里一般是
nextTick
的问题,因为你操作完数据之后,他并没有渲染完毕呢。 - 组件开发中获取 DOM 不方便,有可能出现重复。这里我们可以用
ref
来获取。 - 排序拖动等功能不生效。一般是看上去变了,但是数据不对。因为 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
都会渲染出组件。只不过为 false
时 display:none
解决问题
基于上面的分析我们知道了,因为 v-if
导致组件被销毁,然后再次渲染的时候是根据 Vue 中的数据来渲染的,并没有 DOM 数据。
解决方案一:v-show
既然 v-show
不会销毁,那么我们可以缓存 v-show
。
这个方案的缺点
- 组件在一开始初始化的时候就全部被渲染了。会存在大量请求、无效数据打倒服务器。
- 因为他在一开始就渲染了,所以如果你没有加载完数据的话,存在报错的可能性。
list && list.length
少不了这种代码的存在
解决方案二:切换之后再调用一次
既然 created
的时候是好的,那么我们切换之后再次调用一下初始化渲染不就可以了。
这个方案的缺点
- 因为存在二次渲染,jQuery 等插件一般都会监听事件。所以需要注意事件不能被多次触发。
- 还是因为上个问题,也要注意因为事件引用等问题导致的内存泄漏。
测试DEMO
https://www.lilnong.top/stati...
补一下 DEMO,可以看到一进去四个 input 都是有内容的。
切换之后 v-if 下面的input就有个丢值了。而 v-show 的不受影响。
增加 keep-alive 和组件测试
可以先在 keep-alive 组件中填入内容,然后切换,发现 v-if 的数据没有了
微信公众号:前端linong
欢迎大家关注我的公众号。有疑问也可以加我的微信前端交流群。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。