Vue优化:常见会导致内存泄漏问题及优化详解
如果你在用Vue开发应用,那么就要当心内存泄漏的问题。这个问题在单页应用(SPA)中尤为重要,因为在SPA的设计中,用户使用它时是不需要刷新浏览器的,所以JavaScript应用需要自行清理组件来确保垃圾回收以预期的方式生效。因此在vue开发过程中,你需要时刻警惕内存泄漏的问题,这些内存泄漏往往会发生在使用Vue之外的其它进行DOM操作的三方库时,请确保测试应用的内存泄漏问题并在适当的时机做必要的组件清理。
下面是我开发过程中遇到,并查资料总结的内存泄漏问题,会持续更新中
一、vue自定义指令给元素绑定事件,却没有解绑事件
这个问题见上篇博客,vue自定义指令导致的内存泄漏问题解决
二、v-if指令产生的内存泄露
v-if也是一个容易产生内存泄漏的地方。因为:
1、v-if绑定到false的值,但是实际上dom元素在隐藏的时候没有被真实的释放掉
2、就是非常常见的比如我们通过v-if删除了父级元素,但是并没有移除父级元素里的dom片段。通常产生于使用第三方库的时候,比如下面的示例中,我们加载了一个带有非常多选项的选择框,然后我们用到了一个显示/隐藏按钮,通过一个v-if指令从虚拟DOM中添加或移除它。这个示例的问题在于这个v-if指令会从DOM中移除父级元素,但是我们并没有清除由Choices.js新添加的DOM片段,从而导致了内存泄漏。
Hide Show
newVue({ el:"#app", data:function(){ return{ showChoices:true } }, mounted:function(){ this.initializeChoices() }, methods:{ initializeChoices:function(){ letlist=[] //我们来为选择框载入很多选项 //这样的话它会占用大量的内存 for(leti=0;i<1000;i++){ list.push({ label:"Item"+i, value:i }) } newChoices("#choices-single-default",{ searchEnabled:true, removeItemButton:true, choices:list }) }, show:function(){ this.showChoices=true this.$nextTick(()=>{ this.initializeChoices() }) }, hide:function(){ this.showChoices=false } } })
解决实例:在上述的示例中,我们可以用hide()方法在将选择框从DOM中移除之前做一些清理工作,来解决内存泄露问题。为了做到这一点,我们会在Vue实例的数据对象中保留一个属性,并会使用ChoicesAPI中的destroy()方法将其清除。
newVue({ el:"#app", data:function(){ return{ showChoices:true, choicesSelect:null } }, mounted:function(){ this.initializeChoices() }, methods:{ initializeChoices:function(){ letlist=[] for(leti=0;i<1000;i++){ list.push({ label:"Item"+i, value:i }) } //在我们的Vue实例的数据对象中设置一个`choicesSelect`的引用 this.choicesSelect=newChoices("#choices-single-default",{ searchEnabled:true, removeItemButton:true, choices:list }) }, show:function(){ this.showChoices=true this.$nextTick(()=>{ this.initializeChoices() }) }, hide:function(){ //现在我们可以让Choices使用这个引用 //在从DOM中移除这些元素之前进行清理工作 this.choicesSelect.destroy() this.showChoices=false } } })
三、vue-router跳转到别的组件导致的内容泄漏
在上述示例中,我们使用了一个v-if指令产生内存泄漏,但是一个更常见的实际的场景是使用VueRouter在一个单页应用中路由到不同的组件。
就像这个v-if指令一样,当一个用户在你的应用中导航时,VueRouter从虚拟DOM中移除了元素,并替换为了新的元素。但是其子元素dom片段也并没有销毁。
Vue的beforeDestroy()生命周期钩子是一个解决基于VueRouter的应用中的这类问题的好方法。我们可以将清理工作放入beforeDestroy()钩子,像这样:
beforeDestroy:function(){ this.choicesSelect.destroy() }
所以最正确的解决方案就是:首先,v-if置为false前先删除创建的dom片段;其次,路由跳出吃,在beforeDestroy钩子函数里面判断choicesSelect是否销毁,没销毁则销毁。
还有一个替代方案:
我们已经讨论了移除元素时的内存管理,但是如果你打算在内存中保留状态和元素该怎么做呢?这种情况下,你可以使用内建的keep-alive组件。
当你用keep-alive包裹一个组件后,它的状态就会保留,因此就留在了内存里。
// 即便被删除仍会刻意保留在内存里
这个技巧可以用来提升用户体验。例如,设想一个用户在一个文本框中输入了评论,之后决定导航离开。如果这个用户之后导航回来,那些评论应该还保留着。
一旦你使用了keep-alive,那么你就可以访问另外两个生命周期钩子:activated和deactivated。如果你想要在一个keep-alive组件被移除的时候进行清理或改变数据,可以使用deactivated钩子。
deactivated:function(){ //移除任何你不想保留的数据,或者销毁可能产生内存泄漏的地方 }
以上这篇Vue优化:常见会导致内存泄漏问题及优化详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。