Vue.js中的性能陷阱是什么
本篇内容介绍了"Vue.js中的性能陷阱是什么"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
调查性能下降的原因
我首先使用 Lighthouse 进行了快速测试。所幸 Firefox 为此提供了一个浏览器插件:
https://addons.mozilla.org/en-US/firefox/addon/google-lighthouse/
下面就是我得到的结果。
89%的数字挺不错的。实际上,与许多流行的网站相比,这个表现相当出色。这个测试指出了一些潜在问题,例如速度指数和第一次有意义且有内容的绘制步骤等。从理论上讲,解决这些问题会进一步提高分数,但不一定能解决应用面临的严重性能问题。
我们的游戏中有一些图像和音频素材资源,但是两者都不至于让游戏卡死在那里。我们也可以对这些已经优化过的资源再过度优化一遍,但这可能根本就无济于事。
这个测试无法让我们真正找出可能导致这一性能问题的原因。于是我开始想:"该不会是 Vue 的问题吧?"这种想法会冒出来也没什么理由,但要是不检查一下就是蠢了。我检查了已部署站点的控制台,结果空白一片。但警告往往不会在生产中显示。当我在本地进行相同操作时,一堆 Vue 警告让我吃了一惊。
像大多数开发人员一样,我对控制台警告没那么在意,觉得它们只是警告,而不代表错误;所以我一般会把注意力集中在其他地方。或许消除这些警告可以解决我的生产问题,我决定深入研究每个问题并修复它们。
所有这些警告均来自我创建的、用来显示名为 Cards.vue 选项的组件,因此这个组件可能需要大量重写。
我决定按顺序解决这些控制台警告。
> [Vue warn]: Avoid using non-primitive value as key, use string/number value instead. found in --->at src/components/Cards.vue
Vue.js 有很多指令,让我们能更直观地使用框架,比如说 v-for 就可以快速将数组渲染为列表。使用它时,我们需要一个 :key 才能有效地重渲染组件。但我们将一个对象用作了一个键,这是非原始值,因此导致了这个错误。我决定将 index.description 用作一个新键,因为它是一个字符串,并且在值发生更改时可以更好地重新渲染。
> [Vue warn]: Duplicate keys detected: '[object Object]'. This may cause an update error. found in --->at src/components/Cards.vue
将 :key 更改为一个字符串(index.description)来解决上一个错误,就能解决这个重复键的错误。我们只能将字符串类型写入 DOM,因此当我们传递一个要渲染的对象时,该对象将转换为等效的字符串(即 [object Object]);并且因为这以前是我们的键,所以每个对象都将转换为 [object Object](除非对象有不同的值),进而会出现重复键警告。现在既然键不是对象,警告就会消失,效率也会提升。
> [Vue warn]: You may have an infinite update loop in a component render function. found in --->at src/components/Cards.vue
就一个非常模糊的警告来说,这个警告似乎是最重要的:无限循环意味着内存消耗。这条消息并没有告诉我们可能出了什么问题,但它确实暗示了问题与组件中的 render 函数有关。也许是因为我们写的代码比较取巧,因此触发了不间断的更新,并占用了大量的计算能力,以至于使浏览器和设备崩溃。
这条警告至少告诉我们要检查 Cards.vue,所以我的第一个想法是检查组件中的反应属性,因为这可能会导致错误。反应属性在更改后会触发重新渲染。
我们正在显示 index.days 和 index.description 中的数据。但我们不会更改这些数据,我们从 cardInfo 数组获得 index。
> v-for="index in cardInfo.sort(() => Math.random() - 0.7).slice(0,4)"
我们使用这段代码对数组中的元素进行随机排序,然后将前四个元素显示为玩家选择的选项。当用户单击一个选项时将调用 effects() 函数,它除了会计算一个动作如何影响游戏状态外,还使用 cardInfo 上的拼接原型删除前四个元素。
在 Vue 这种使用虚拟 DOM 的框架里,用上诸如 cardInfo 之类的反应属性后,每当数据属性的值更改时都会触发重新渲染。在我们的应用里,我们会直接使用 sort() 原型来更改它,然后删除元素来重新排序。所有这些都会触发"无限"的重新渲染,从而引发警告。
我决定更改数据过滤的逻辑,并停止对反应属性 cardInfo 的多次更改。我安装了 lodash.shuffle 并定义了一个计算属性 shuffledList(),它将创建一个名为 list 的 cardInfo 副本。我对其应用了随机排序操作,并返回了一个"frozen"结果,然后拆分开来显示四张卡片。我们使用了 Object.freeze(),它将使我们返回的对象不可变,从而完全停止了所有重新渲染操作。
至此,问题解决了。
掉进框架的坑
老实说,当我刚开始调查性能下降原因的时候,还觉得我肯定要优化很多资源才能解决问题。最后这个结果说明,在使用许多框架抽象时我们都必须非常小心——特别是在 Vue 中更是如此,只有在必要时才使用某条指令,而且用法一定不能出错,因为它们绝对有自己的代价。
这还让我开始思考自己做过的其他工作,其中应用程序可能会因为框架而出现不必要的性能问题。大多数现代的前端框架都有很多抽象,使我们能更轻松地为 Web 制作应用程序。但我们应该牢记一点,那就是使用这些东西可能会引发潜在的性能问题。
我经常使用 Vue.js,所以决定探索一些我以前用过的指令,以前我用这些指令的时候完全没考虑过它们可能对应用程序带来的性能影响。其中有三条非常流行的指令进入了我的视线。
1. v-if 和 v-show
这两条指令都是用来有条件地渲染元素的,但是它们背后的工作机制却大不相同,因此用法也大相径庭。v-if 一开始不会渲染组件,而只在条件为真时才渲染组件。这意味着当你多次切换组件的可见性时,就会不断重新渲染。如果你要多次更改组件的可见性,那就不要使用这个功能。这会影响你的性能。
v-show 是一个很好的替代品。不管你是否启用 CSS 都会渲染你的组件,但是只会根据条件是 true 还是 false 来决定组件是否可见。这种方法确实有其缺点,因为它不会将非必要组件的渲染推迟到你需要它们在屏幕上实际出现的时候。如果你的初始渲染没那么复杂,那么它就很合适。
2. v-for
这条指令通常用来从数组中渲染列表。它有一个特殊的语法,形式为 item in list,其中 list 是源数据数组,而 item 是要迭代的数组元素的别名。默认情况下,Vue 在源数据数组上添加 watchers,每当发生更改时它就会触发重新渲染。这种持续的重新渲染可能会对应用程序性能产生不利影响。如果你只想可视化对象,那么 Object.freeze() 是一个很好的解决方案,可以大大提高性能。但是请务必记住,你将无法更新组件或编辑对象数据。
在这个研究过程中我还意识到,Lighthouse 可能检查的是以更直接的方式影响用户体验的应用性能指标,所以接下来我的疑问就是如何跟踪服务器上的应用程序性能。
"Vue.js中的性能陷阱是什么"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!