首頁 > 軟體

如何手動銷燬Vue中掛載的元件

2022-08-09 14:01:54

手動銷燬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.’ 不會對頁面產生影響。 

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。 


IT145.com E-mail:sddin#qq.com