Evan You 11 лет назад
Родитель
Сommit
6bc60e9f24

+ 1 - 0
component.json

@@ -28,6 +28,7 @@
     "src/directives/cloak.js",
     "src/directives/component.js",
     "src/directives/el.js",
+    "src/directives/events.js",
     "src/directives/html.js",
     "src/directives/if.js",
     "src/directives/index.js",

+ 27 - 0
src/directives/events.js

@@ -0,0 +1,27 @@
+var _ = require('../util')
+
+module.exports = { 
+
+  bind: function () {
+    var child = this.el.__vue__
+    if (!child || this.vm !== child.$parent) {
+      _.warn(
+        '`v-events` should only be used on a child component ' +
+        'from the parent template.'
+      )
+      return
+    }
+    var method = this.vm[this.expression]
+    if (!method) {
+      _.warn(
+        '`v-events` cannot find method "' + this.expression +
+        '" on the parent instance.'
+      )
+    }
+    child.$on(this.arg, method)
+  }
+
+  // when child is destroyed, all events are turned off,
+  // so no need for unbind here.
+
+}

+ 4 - 1
src/directives/index.js

@@ -19,4 +19,7 @@ exports.model      = require('./model')
 exports.component  = require('./component')
 exports.repeat     = require('./repeat')
 exports['if']      = require('./if')
-exports['with']    = require('./with')
+
+// child vm communication directives
+exports['with']    = require('./with')
+exports.events     = require('./events')

+ 3 - 9
src/directives/ref.js

@@ -6,16 +6,10 @@ module.exports = {
 
   bind: function () {
     var child = this.el.__vue__
-    if (!child) {
+    if (!child || this.vm !== child.$parent) {
       _.warn(
-        'v-ref should only be used on instance root nodes.'
-      )
-      return
-    }
-    if (this.vm !== child.$parent) {
-      _.warn(
-        'v-ref should be used from the parent template,' +
-        ' not the component\'s.'
+        'v-ref should only be used on a child component ' +
+        'from the parent template.'
       )
       return
     }

+ 74 - 0
test/unit/specs/directives/events_spec.js

@@ -0,0 +1,74 @@
+var _ = require('../../../../src/util')
+var Vue = require('../../../../src/vue')
+
+if (_.inBrowser) {
+  describe('v-events', function () {
+
+    var el
+    beforeEach(function () {
+      spyOn(_, 'warn')
+      el = document.createElement('div')
+    })
+
+    it('should register events', function () {
+      var spy = jasmine.createSpy('v-events')
+      new Vue({
+        el: el,
+        template: '<div v-component="test" v-events="test:test"></div>',
+        methods: {
+          test: spy
+        },
+        components: {
+          test: {
+            compiled: function () {
+              this.$emit('test')
+            }
+          }
+        }
+      })
+      expect(spy).toHaveBeenCalled()
+    })
+
+    it('should warn when used on non-root node', function () {
+      new Vue({
+        el: el,
+        template: '<div v-events="test:test"></div>'
+      })
+      expect(_.warn).toHaveBeenCalled()
+    })
+
+    it('should warn when used on child component root', function () {
+      var spy = jasmine.createSpy('v-events')
+      new Vue({
+        el: el,
+        template: '<div v-component="test"></div>',
+        methods: {
+          test: spy
+        },
+        components: {
+          test: {
+            replace: true,
+            template: '<div v-events="test:test"></div>',
+            compiled: function () {
+              this.$emit('test')
+            }
+          }
+        }
+      })
+      expect(_.warn).toHaveBeenCalled()
+      expect(spy).not.toHaveBeenCalled()
+    })
+
+    it('should warn when method not found on parent', function () {
+      new Vue({
+        el: el,
+        template: '<div v-component="test" v-events="test:test"></div>',
+        components: {
+          test: {}
+        }
+      })
+      expect(_.warn).toHaveBeenCalled()
+    })
+
+  })
+}

+ 15 - 1
test/unit/specs/directives/ref_spec.js

@@ -63,7 +63,7 @@ if (_.inBrowser) {
       expect(vm.$.c1.$.c2.length).toBe(2)
     })
 
-    it('warn on non-root', function () {
+    it('should warn on non-root', function () {
       var vm = new Vue({
         el: el,
         template: '<div v-ref="test"></div>'
@@ -71,5 +71,19 @@ if (_.inBrowser) {
       expect(_.warn).toHaveBeenCalled()
     })
 
+    it('should warn when used in child template', function () {
+      var vm = new Vue({
+        el: el,
+        template: '<div v-component="test"></div>',
+        components: {
+          test: {
+            template: '<div v-ref="test"></div>',
+            replace: true
+          }
+        }
+      })
+      expect(_.warn).toHaveBeenCalled()
+    })
+
   })
 }