Просмотр исходного кода

fragment: destroy children before removal

Evan You 10 лет назад
Родитель
Сommit
012bede3f3
4 измененных файлов с 34 добавлено и 20 удалено
  1. 2 2
      src/directives/public/for.js
  2. 2 2
      src/directives/public/if.js
  3. 20 12
      src/fragment/fragment.js
  4. 10 4
      src/instance/lifecycle.js

+ 2 - 2
src/directives/public/for.js

@@ -325,11 +325,11 @@ module.exports = {
     if (inDoc && staggerAmount) {
       var op = frag.staggerCb = _.cancellable(function () {
         frag.staggerCb = null
-        frag.remove(true)
+        frag.remove()
       })
       setTimeout(op, staggerAmount)
     } else {
-      frag.remove(true)
+      frag.remove()
     }
   },
 

+ 2 - 2
src/directives/public/if.js

@@ -40,7 +40,7 @@ module.exports = {
 
   insert: function () {
     if (this.elseFrag) {
-      this.elseFrag.remove(true)
+      this.elseFrag.remove()
       this.elseFrag = null
     }
     this.frag = this.factory.create(this._host, this._scope, this._frag)
@@ -49,7 +49,7 @@ module.exports = {
 
   remove: function () {
     if (this.frag) {
-      this.frag.remove(true)
+      this.frag.remove()
       this.frag = null
     }
     if (this.elseFactory) {

+ 20 - 12
src/fragment/fragment.js

@@ -89,21 +89,18 @@ function singleBefore (target, withTransition) {
 
 /**
  * Remove fragment, single node version
- *
- * @param {Boolean} [destroy]
  */
 
-function singleRemove (destroy) {
+function singleRemove () {
   this.inserted = false
   var shouldCallRemove = _.inDoc(this.node)
   var self = this
+  self.callHook(destroyChild)
   transition.remove(this.node, this.vm, function () {
     if (shouldCallRemove) {
       self.callHook(detach)
     }
-    if (destroy) {
-      self.destroy()
-    }
+    self.destroy()
   })
 }
 
@@ -130,21 +127,18 @@ function multiBefore (target, withTransition) {
 
 /**
  * Remove fragment, multi-nodes version
- *
- * @param {Boolean} [destroy]
  */
 
-function multiRemove (destroy) {
+function multiRemove () {
   this.inserted = false
   var self = this
   var shouldCallRemove = _.inDoc(this.node)
+  self.callHook(destroyChild)
   _.removeNodeRange(this.node, this.end, this.vm, this.frag, function () {
     if (shouldCallRemove) {
       self.callHook(detach)
     }
-    if (destroy) {
-      self.destroy()
-    }
+    self.destroy()
   })
 }
 
@@ -160,6 +154,20 @@ function attach (child) {
   }
 }
 
+/**
+ * Call destroy for all contained instances,
+ * with remove:false and defer:true.
+ * Defer is necessary because we need to
+ * keep the children to call detach hooks
+ * on them.
+ *
+ * @param {Vue} child
+ */
+
+function destroyChild (child) {
+  child.$destroy(false, true)
+}
+
 /**
  * Call detach hook for a Vue instance.
  *

+ 10 - 4
src/instance/lifecycle.js

@@ -123,6 +123,7 @@ exports._bindDir = function (descriptor, node, host, scope, frag) {
 
 exports._destroy = function (remove, deferCleanup) {
   if (this._isBeingDestroyed) {
+    this._cleanup()
     return
   }
   this._callHook('beforeDestroy')
@@ -142,10 +143,6 @@ exports._destroy = function (remove, deferCleanup) {
       }
     }
   }
-  // remove self from owner fragment
-  if (this._frag) {
-    this._frag.children.$remove(this)
-  }
   // destroy all children.
   i = this.$children.length
   while (i--) {
@@ -186,6 +183,15 @@ exports._destroy = function (remove, deferCleanup) {
  */
 
 exports._cleanup = function () {
+  if (this._isDestroyed) {
+    return
+  }
+  // remove self from owner fragment
+  // do it in cleanup so that we can call $destroy with
+  // defer right when a fragment is about to be removed.
+  if (this._frag) {
+    this._frag.children.$remove(this)
+  }
   // remove reference from data ob
   // frozen object may not have observer.
   if (this._data.__ob__) {