手动销毁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.’ 不会对页面产生影响。 

以上为个人经验,希望能给大家一个参考,也希望大家多多支持阿兔在线工具。 

点赞(0)

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部