Parcourir la source

adjust $destroy procedure so final cleanup happens after transition finishes

Evan You il y a 11 ans
Parent
commit
1592a0607f
5 fichiers modifiés avec 43 ajouts et 49 suppressions
  1. 2 0
      changes.md
  2. 35 19
      src/api/lifecycle.js
  3. 1 1
      src/directive.js
  4. 5 16
      src/directives/component.js
  5. 0 13
      test/unit/specs/directive_spec.js

+ 2 - 0
changes.md

@@ -197,6 +197,8 @@ By default, all child components **DO NOT** inherit the parent scope. Only anony
 
   - #### renamed hook: `afterDestroy` -> `destroyed`
 
+    Additionally, if there is a leaving transition, `beforeDestroy` is called before the transition starts, and `destroyed` will be called **after** the transition has finished (right after `detached`).
+
 ## Instance methods change
 
 - #### `vm.$watch`

+ 35 - 19
src/api/lifecycle.js

@@ -64,10 +64,6 @@ exports.$destroy = function (remove) {
   }
   this._callHook('beforeDestroy')
   this._isBeingDestroyed = true
-  // remove DOM element
-  if (remove && this.$el) {
-    this.$remove()
-  }
   var i
   // remove self from parent. only necessary
   // if parent is not being destroyed as well.
@@ -93,27 +89,47 @@ exports.$destroy = function (remove) {
   for (i in this._userWatchers) {
     this._userWatchers[i].teardown()
   }
-  // clean up
+  // remove reference to self on $el
   if (this.$el) {
     this.$el.__vue__ = null
   }
+  // remove DOM element
+  var self = this
+  if (remove && this.$el) {
+    this.$remove(function () {
+      cleanup(self)
+    })
+  } else {
+    cleanup(self)
+  }
+}
+
+/**
+ * Clean up to ensure garbage collection.
+ * This is called after the leave transition if there
+ * is any.
+ *
+ * @param {Vue} vm
+ */
+
+function cleanup (vm) {
   // remove reference from data ob
-  this._data.__ob__.removeVm(this)
-  this._data =
-  this._watchers =
-  this._userWatchers =
-  this._watcherList =
-  this.$el =
-  this.$parent =
-  this.$root =
-  this._children =
-  this._bindings =
-  this._directives = null
+  vm._data.__ob__.removeVm(vm)
+  vm._data =
+  vm._watchers =
+  vm._userWatchers =
+  vm._watcherList =
+  vm.$el =
+  vm.$parent =
+  vm.$root =
+  vm._children =
+  vm._bindings =
+  vm._directives = null
   // call the last hook...
-  this._isDestroyed = true
-  this._callHook('destroyed')
+  vm._isDestroyed = true
+  vm._callHook('destroyed')
   // turn off all instance listeners.
-  this.$off()
+  vm.$off() 
 }
 
 /**

+ 1 - 1
src/directive.js

@@ -75,7 +75,7 @@ p._bind = function (def) {
     // wrapped updater for context
     var dir = this
     var update = this._update = function (val, oldVal) {
-      if (!dir._locked && !dir.vm._isBeingDestroyed) {
+      if (!dir._locked) {
         dir.update(val, oldVal)
       }
     }

+ 5 - 16
src/directives/component.js

@@ -117,25 +117,14 @@ module.exports = {
         child.$remove()
       }
     } else {
+      child.$destroy(remove)
       var parentDirs = this.parentDirs
-      var destroy = function () {
-        child.$destroy()
-        if (parentDirs) {
-          var i = parentDirs.length
-          while (i--) {
-            parentDirs[i]._teardown()
-          }
+      if (parentDirs) {
+        var i = parentDirs.length
+        while (i--) {
+          parentDirs[i]._teardown()
         }
       }
-      if (remove) {
-        // setting the "being destroyed" flag before
-        // removing to avoid content being changed during
-        // transitions
-        child._isBeingDestroyed = true
-        child.$remove(destroy)
-      } else {
-        destroy()
-      }
     }
     this.childVM = null
   },

+ 0 - 13
test/unit/specs/directive_spec.js

@@ -177,17 +177,4 @@ describe('Directive', function () {
     })
   })
 
-  it('avoid update when vm is being destroyed', function (done) {
-    var d = new Directive('test', el, vm, {
-      expression: 'a',
-    }, def)
-    expect(def.update.calls.count()).toBe(1)
-    vm._isBeingDestroyed = true
-    vm.a = 2
-    nextTick(function () {
-      expect(def.update.calls.count()).toBe(1)
-      done()
-    })
-  })
-
 })