あなたはVueのを使用してアプリケーションを開発する場合、我々はメモリリークに注意する必要があります。JavaScriptアプリケーションが期待される形で発効を確保するために、独自のガベージコレクションのコンポーネントをクリーンアップする必要があるので、SPAのデザインは、ユーザーは、ブラウザを更新するためにそれを使用する必要はありませんので、この問題は、1ページのアプリケーション(SPA)において特に重要です。したがって、開発プロセスにおけるVUE、あなたが警戒メモリリークする必要があり、これらのメモリリークは、メモリリークテストアプリケーションことと適切なタイミングでの確保、三者VueのDOMライブラリの操作以外の使用で発生する傾向がありますクリーンアップするために必要なコンポーネントを実行します。
ここで私は、開発プロセスで遭遇するものであり、メモリリーク情報の概要を確認し、我々は、更新していきます
、VUEカスタムコマンド要素は、イベントに結合したが、無アンバンドリングイベントです
この問題は、ブログの記事を参照の上、メモリリークからVUE定義命令を解決する原因
二、V-IF命令生成メモリリーク
V-場合も、メモリリークが発生しやすい場所。理由は次のとおりです。
1は、V-場合は偽の値にバインドされますが、本当の解放がない場合、実際にDOM要素が隠されています
2は、非常に一般的な例である、我々は、V-場合によって親要素を削除しますが、DOMフラグメントに親要素を削除しませんでした。サードパーティのライブラリを使用する場合に通常作成され、次の例のような、我々は非常に多くのオプションを搭載した選択ボックスを持っている、と我々はを通じて、表示/非表示]ボタンを使用して 、V-場合 の仮想DOMからの命令を追加またはそれを削除してください。問題の例は、このことにある v-if
コマンドはDOMから親要素を削除しますが、我々はメモリリークが生じ、新しく追加されたChoices.jsからDOMフラグメントをクリアしていませんでした。
<リンクのrel = " スタイルシートのプリフェッチ"のhref = " https://joshuajohnson.co.uk/Choices/assets/styles/css/choices.min.css?version=3.0.3 " >
<スクリプトSRC = " HTTPS:/ /joshuajohnson.co.uk/Choices/assets/scripts/dist/choices.min.js?version=3.0.3 " > </ SCRIPT>
の<divのid = " アプリ" >
<ボタンV- 場合 = " showChoices " @ =]をクリックし、 " 非表示" >隠す</ button>の
<ボタンをV- 場合 = " !showChoices " @ =クリック" ショー" >表示</ button>の
<divのV- 場合 = " showChoices " >
< 選択のid = " 選択肢-シングルデフォルト" > </ 選択 >
</ div>
</ div>
新しい新しいヴュー({
EL:" #app " 、
データ:機能(){
リターン{
showChoices:trueに
}
}、
マウント:機能(){
この.initializeChoices()
}、
メソッド:{
initializeChoices:機能(){
letの一覧 = []
// 我々はボックスを選択するために、多くのオプションをロードする必要が
// これは、それが大量のメモリを取り上げるケースである
ため(LET私は= 0 ;私は< 1000 ; iの++ ){
list.push({
ラベル:「アイテム」 +私は、
値:I
})
}
新しい選択肢(" #選択肢-シングルデフォルト" 、{
searchEnabled:真、
removeItemButton:真、
選択肢:リスト
})
}、
ショー:機能(){
この .showChoicesは= 真
これを。$ nextTick(()=> {
この.initializeChoices()
})
}、
非表示:関数(){
この .showChoices = 偽
}
}
})
解决实例:在上述的示例中,我们可以用 hide()
方法在将选择框从 DOM 中移除之前做一些清理工作,来解决内存泄露问题。为了做到这一点,我们会在 Vue 实例的数据对象中保留一个属性,并会使用 Choices API 中的 destroy()
方法将其清除。
new Vue({
el: "#app",
data: function () {
return {
showChoices: true,
choicesSelect: null
}
},
mounted: function () {
this.initializeChoices()
},
methods: {
initializeChoices: function () {
let list = []
for (let i = 0; i < 1000; i++) {
list.push({
label: "Item " + i,
value: i
})
}
// 在我们的 Vue 实例的数据对象中设置一个 `choicesSelect` 的引用
this.choicesSelect = new Choices("#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
指令产生内存泄漏,但是一个更常见的实际的场景是使用 Vue Router 在一个单页应用中路由到不同的组件。
就像这个 v-if
指令一样,当一个用户在你的应用中导航时,Vue Router 从虚拟 DOM 中移除了元素,并替换为了新的元素。但是其子元素dom片段也并没有销毁。
Vue 的 beforeDestroy()
生命周期钩子是一个解决基于 Vue Router 的应用中的这类问题的好方法。我们可以将清理工作放入 beforeDestroy()
钩子,像这样:
beforeDestroy: function () {
this.choicesSelect.destroy()
}
所以最正确的解决方案就是:首先,v-if置为false前先删除创建的dom片段;其次,路由跳出吃,在beforeDestroy钩子函数里面判断choicesSelect是否销毁,没销毁则销毁。
还有一个替代方案:
我们已经讨论了移除元素时的内存管理,但是如果你打算在内存中保留状态和元素该怎么做呢?这种情况下,你可以使用内建的 keep-alive 组件。
当你用 keep-alive
包裹一个组件后,它的状态就会保留,因此就留在了内存里。
<button @click="show = false">Hide</button>
<keep-alive>
// <my-component> 即便被删除仍会刻意保留在内存里
<my-component v-if="show"></my-component>
</keep-alive>
这个技巧可以用来提升用户体验。例如,设想一个用户在一个文本框中输入了评论,之后决定导航离开。如果这个用户之后导航回来,那些评论应该还保留着。
一旦你使用了 keep-alive
,那么你就可以访问另外两个生命周期钩子:activated
和 deactivated
。如果你想要在一个 keep-alive
组件被移除的时候进行清理或改变数据,可以使用 deactivated
钩子。
deactivated: function () {
// 移除任何你不想保留的数据,或者销毁可能产生内存泄漏的地方
}