「前端优化必学」v-model 陷阱,连续输入瞬间卡半天?!

v-model 是 Vue 中最常用的属性之一,它可以实现数据和表单元素的双向绑定,让我们的开发更加方便。

但是你知道吗?在绑定文本框时,如果不注意使用方式,v-model 会带来严重的性能问题。这些问题可能会影响用户体验,比如页面卡顿、动画元素闪动等。

那么,这些问题是怎么产生的呢?又该如何解决呢?

我是渡一前端子辰老师,今天我们一起来探究一下吧

问题产生的原因

我们先来看一个例子,我们有一个输入框和一个列表,输入框使用了 v-model 绑定了一个数据,列表使用了 Vue 的列表过渡效果,还有一个按钮可以对列表进行随机排序。

我们可以看到,当我们点击按钮进行随机排序时,列表的过渡效果很流畅。

但是,如果我们在随机排序的同时,在输入框中连续输入文字,会发生什么呢?

我们可以看到,当我们连续输入文字时,列表的过渡效果变得非常卡顿,当我们停止输入后,过渡效果又恢复正常。

这是为什么呢?其实原因很简单,就是因为 v-model 的双向绑定机制。v-model 其实是 :value + @input 组合的语法糖,也就是说,当文本框的值发生变化时,会触发 @input 事件,并更新绑定的数据。

而当数据发生变化时,Vue 会重新渲染组件,并更新文本框的值。

这样一来,如果我们在文本框中频繁输入文字,就会导致组件频繁重新渲染。

如果我们手速很快,一秒钟可以输入几十个字,那么组件就会在一秒钟内渲染几十次。

而组件的渲染其实是一个 JS 行为,而 JS 的执行会阻塞浏览器的其他动作,比如动画效果。

所以当组件渲染太频繁时,就会造成页面卡顿和动画闪动。

我们可以用浏览器的 Performance 工具来验证一下这个原因。

我们在输入框中输入了 12345 五个数字,并记录了性能数据。

从上图中我们可以看到,在输入框中每输入一个数字,都会触发一次组件的重新渲染。连续输入了 12345 五个数字,就导致了重新渲染五次。

你可能会奇怪,Vue 不是说过它在更新 DOM 时是异步执行的吗?它不是说它会开启一个队列,并缓冲在同一事件循环中发生的所有数据变更吗?它不是说如果同一个 watcher 被多次触发,只会被推入到队列中一次吗?

为什么 v-model 就不遵循这个规则呢?

其实这是因为 v-model 的实现机制和所说的响应式不太一样,v-model 其实是 :value + @input 组合的语法糖,当文本框 change 时会触发 watch 与 computed 函数,属性的变化走的是 defineProperty。而 watcher 走的是观察者模式,所以才用到了队列。

那么既然知道了问题产生的原因,我们就可以想办法解决它了。

问题解决的方法

其实解决这个问题很简单,只要让 v-model 不要那么敏感就行了。

也就是说,不要让它每次文本框的值变化就去更新数据和重新渲染组件,而要让它在合适的时机去做这些事情。

那么什么时候是合适的时机呢?答案是:当文本框失去焦点时。

也就是说,当用户完成了输入,并点击了其他地方或者按下了回车键时,才去更新数据和重新渲染组件。

这样就可以大大减少组件渲染的频率,并避免页面卡顿和动画闪动。

那么如何让 v-model 在文本框失去焦点时才更新数据和重新渲染组件呢?

其实很简单,只要给 v-model 加上一个修饰符 v-model.lazy 就行了。这个修饰符可以让 v-model 监听文本框的 change 事件而不是 input 事件。

也就是说,在文本框失去焦点时才触发事件,并更新数据和重新渲染组件。

xml 复制代码
<!-- v-model -->
<input v-model="..." />
<!-- v-model 就是 :value + @input 组合的语法糖-->
<input :value="..." @input="..." />
<!-- 当加了 .lazy 修饰符之后 -->
<input v-model.lazy="..." />
<!-- v-model 就变成了 :value + @change 组合的语法糖 -->
<input :value="..." @change="..." />

我们来看看加上这个修饰符后的效果吧。

从上图中我们可以看到,在随机排序期间无论我们怎么输入文字都不会影响动画效果了。

因为此时没有触发任何事件或者重新渲染组件。

只有当我们点击其他地方或者按下回车键后才会更新数据和重新渲染组件。

当然这种方法也有一个缺点,就是在一段时间内数据和文本框显示的内容不一致。

比如下图所示:

总结

通过这个例子我们可以学习到一个重要的优化技巧:减少不必要的组件重新渲染。

有时候我们可能不注意使用方式或者场景需求而导致组件重新渲染太频繁而影响性能和用户体验。

所以我们要根据具体情况具体分析,在保证功能正常运行的前提下尽量减少组件重新渲染的次数。

当然这只是 Vue 中众多优化技巧中的一小部分,Vue 还有很多其他优化技巧等待你去探索和学习。

本文来源

本文来源自渡一官方公众号:Duing ,欢迎关注,获取最新最全最深入的技术讲解

感谢你阅读本文,如果你有任何疑问或建议,请在评论区留言,如果你觉得这篇文章有用,请点赞收藏或分享给你的朋友!

相关推荐
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅5 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
吹牛不交税6 小时前
admin.net-v2 框架使用笔记-netcore8.0/10.0版
vue.js·.netcore
Cobyte6 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc
NEXT066 小时前
前端算法:从 O(n²) 到 O(n),列表转树的极致优化
前端·数据结构·算法