Răsfoiți Sursa

fix #561 attach/detach/ready hooks for children in partial compile blocks

Evan You 11 ani în urmă
părinte
comite
4339243f4a
3 a modificat fișierele cu 52 adăugiri și 33 ștergeri
  1. 30 11
      src/directives/if.js
  2. 10 21
      src/directives/partial.js
  3. 12 1
      test/unit/specs/directives/if_spec.js

+ 30 - 11
src/directives/if.js

@@ -45,24 +45,43 @@ module.exports = {
   insert: function () {
     // avoid duplicate inserts, since update() can be
     // called with different truthy values
-    if (this.decompile) {
-      return
+    if (!this.unlink) {
+      this.compile(this.template) 
     }
+  },
+
+  compile: function (template) {
     var vm = this.vm
-    var frag = templateParser.clone(this.template)
-    var decompile = this.linker(vm, frag)
-    this.decompile = function () {
-      decompile()
-      transition.blockRemove(this.start, this.end, vm)
-    }
+    var frag = templateParser.clone(template)
+    var originalChildLength = vm._children
+      ? vm._children.length
+      : 0
+    this.unlink = this.linker
+      ? this.linker(vm, frag)
+      : vm.$compile(frag)
     transition.blockAppend(frag, this.end, vm)
+    this.children = vm._children
+      ? vm._children.slice(originalChildLength)
+      : null
+    if (this.children && _.inDoc(vm.$el)) {
+      this.children.forEach(function (child) {
+        child._callHook('attached')
+      })
+    }
   },
 
   teardown: function () {
-    if (this.decompile) {
-      this.decompile()
-      this.decompile = null
+    if (!this.unlink) return
+    transition.blockRemove(this.start, this.end, this.vm)
+    if (this.children && _.inDoc(this.vm.$el)) {
+      this.children.forEach(function (child) {
+        if (!child._isDestroyed) {
+          child._callHook('detached')
+        }
+      })
     }
+    this.unlink()
+    this.unlink = null
   }
 
 }

+ 10 - 21
src/directives/partial.js

@@ -1,11 +1,15 @@
 var _ = require('../util')
 var templateParser = require('../parse/template')
-var transition = require('../transition')
+var vIf = require('./if')
 
 module.exports = {
 
   isLiteral: true,
 
+  // same logic reuse from v-if
+  compile: vIf.compile,
+  teardown: vIf.teardown,
+
   bind: function () {
     var el = this.el
     this.start = document.createComment('v-partial-start')
@@ -20,35 +24,20 @@ module.exports = {
     }
     _.before(this.start, this.end)
     if (!this._isDynamicLiteral) {
-      this.compile(this.expression)
+      this.insert(this.expression)
     }
   },
 
   update: function (id) {
     this.teardown()
-    this.compile(id)
+    this.insert(id)
   },
 
-  compile: function (id) {
+  insert: function (id) {
     var partial = this.vm.$options.partials[id]
     _.assertAsset(partial, 'partial', id)
-    if (!partial) {
-      return
-    }
-    var vm = this.vm
-    var frag = templateParser.parse(partial, true)
-    var decompile = vm.$compile(frag)
-    this.decompile = function () {
-      decompile()
-      transition.blockRemove(this.start, this.end, vm)
-    }
-    transition.blockAppend(frag, this.end, vm)
-  },
-
-  teardown: function () {
-    if (this.decompile) {
-      this.decompile()
-      this.decompile = null
+    if (partial) {
+      this.compile(templateParser.parse(partial))
     }
   }
 

+ 12 - 1
test/unit/specs/directives/if_spec.js

@@ -70,6 +70,9 @@ if (_.inBrowser) {
     })
 
     it('v-if + v-component', function (done) {
+      var attachSpy = jasmine.createSpy()
+      var detachSpy = jasmine.createSpy()
+      var readySpy = jasmine.createSpy()
       var vm = new Vue({
         el: el,
         data: { ok: false },
@@ -79,20 +82,28 @@ if (_.inBrowser) {
             data: function () {
               return { a: 123 }
             },
-            template: '{{a}}'
+            template: '{{a}}',
+            ready: readySpy,
+            attached: attachSpy,
+            detached: detachSpy
           }
         }
       })
+      vm.$appendTo(document.body)
       expect(el.innerHTML).toBe(wrap(''))
       expect(vm._children).toBeNull()
       vm.ok = true
       _.nextTick(function () {
         expect(el.innerHTML).toBe(wrap('<div>123</div><!--v-component-->'))
         expect(vm._children.length).toBe(1)
+        expect(attachSpy).toHaveBeenCalled()
+        expect(readySpy).toHaveBeenCalled()
         vm.ok = false
         _.nextTick(function () {
+          expect(detachSpy).toHaveBeenCalled()
           expect(el.innerHTML).toBe(wrap(''))
           expect(vm._children.length).toBe(0)
+          vm.$remove()
           done()
         })
       })