如何手動銷毀Vue中掛載的組件

手動銷毀Vue掛載的組件

因為很多頁面需要用到<keep-alive>,我就用其將承載頁面的父組件包裹瞭,但這也帶來瞭一些問題。比如新寫的頁面中,進入下個頁面還在調用上個頁面的數據(以前沒有遇到過,不清楚是是什麼原因),即已經切換路由卻無法自己destory掉,打日志發現確實沒有跑destoryed這個生命周期函數。

如何解決

在需要刪除的組件中的deactivated生命周期函數中手動調用this.$destroy('componentName'),這裡的componentName即這個組件的name,使用後發現destoryed函數確實可以正常使用瞭,而且進入下一個頁面也不會再報錯說缺少這個頁面的數據。

vue 銷毀實例

1.導入vue創建一個VM實例

傳入配置對象,瞭解配置對象中的各個屬性

var VM = new Vue({ el: '#app', // 表示當我們new的這個Vue實例, 要控制頁面上的那個區域 
data: { // data屬性中,存放的是el中要用到的數據,這裡的data就是MVVM中的M專門用來保存每個頁面的數據 message: 'Hello Vue!' }, 
methods : {}, // 這個methods屬性中定義瞭當前Vue實例所有可用的方法,主要寫業務邏輯 
computed: {}, // 在computed中,可以定一些屬性, 這些屬性叫做計算屬性,計算屬性的本質就是一個方法,隻不過我們在使用這些計算屬性的時候是吧它們的名稱直接當做屬性來使用的,並不會把計算屬性當做方法去調用 
filters : {}, // 這個filters屬性中定義瞭當前Vue實例中所有可用的過濾的方法 
watch: {}, // 使用這個屬性,可以監聽data中數據的變化,然後觸發這個watch中對應的function處理函數 router, // 掛載路由對象 
directives:{}, // 這個directives屬性定義瞭當前Vue實例中所有可用的自定義指令 beforeCreate () {}, // 生命周期函數: 表示實例完全被創建之前,會執行這個函數 
created () {}, // 生命周期函數: 表示實例被創建之後 
beforeMounted () {}, // 生命周期函數: 表示模板已經編譯完成,但是還沒有把模板渲染到頁面中 
mounted () {}, // 生命周期函數:表示模板已經編譯完成,內存中的模板已經真實的渲染到瞭頁面中去,已經可以看到渲染好的頁面瞭 
beforeUpdate () {}, // 生命周期函數: 表示當前界面還沒有被更新,數據肯定被更新瞭 
update () {}, // 生命周期函數: 表示當前頁面和數據保持同步瞭,都是最新的 
beforeDestroy () {}, // 生命周期函數: 表示Vue實例已經從運行階段進入到銷毀階段 
destroyed () {} // 生命周期函數: 表示組件已經完全被銷毀瞭})

2.vm.$destroy()隻能銷毀實例裡的方法但不能清除DOM和data嗎?

destroy()隻是完全銷毀一個實例,清理它與其它實例的連接,解綁它的全部指令及事件監聽器。

參見官方文檔: https://cn.vuejs.org/v2/api/#vm-destroy

它並不是用來清除已有頁面上的DOM的。實現功能包括:

(1) 包括Watcher對象從其所在Dep中釋放

if (vm._watcher) {
  vm._watcher.teardown()
}
let i = vm._watchers.length
while (i--) {
  vm._watchers[i].teardown()
}
// remove reference from data ob
// frozen object may not have observer.
if (vm._data.__ob__) {
  vm._data.__ob__.vmCount--
}

(2) 移除所有事件的監聽

vm.$off()

(3) patch一個null目的是觸發所有的destroy鉤子。

vm.__patch__(vm._vnode, null)
return function patch (oldVnode, vnode, hydrating, removeOnly, parentElm, refElm) {
    /*vnode不存在則直接調用銷毀鉤子*/
    if (isUndef(vnode)) {
      if (isDef(oldVnode)) invokeDestroyHook(oldVnode)
      return
    }
    ...
 }

想要清除頁面的 DOM,需要使用 v-if,或者修改 v-for 中涉及到的數組或對象。

另外,調用 app.$destroy() 之後,你會發現,app.message = ‘Yes, he is a boy.’ 不會對頁面產生影響。 

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。 

推薦閱讀: