Evan You 10 роки тому
батько
коміт
d62eacd1da

+ 9 - 8
src/core/util/options.js

@@ -206,7 +206,7 @@ const defaultStrat = function (parentVal: any, childVal: any): any {
  * Make sure component options get converted to actual
  * constructors.
  */
-function guardComponents (options: Object) {
+function normalizeComponents (options: Object) {
   if (options.components) {
     const components = options.components
     let def
@@ -230,7 +230,7 @@ function guardComponents (options: Object) {
  * Ensure all props option syntax are normalized into the
  * Object-based format.
  */
-function guardProps (options: Object) {
+function normalizeProps (options: Object) {
   const props = options.props
   if (!props) return
   const res = {}
@@ -261,12 +261,13 @@ function guardProps (options: Object) {
 /**
  * Normalize raw function directives into object format.
  */
-function guardDirectives (options: Object) {
+function normalizeDirectives (options: Object) {
   const dirs = options.directives
   if (dirs) {
     for (const key in dirs) {
-      if (typeof dirs[key] === 'function') {
-        dirs[key] = { update: dirs[key] }
+      const def = dirs[key]
+      if (typeof def === 'function') {
+        dirs[key] = { bind: def, update: def }
       }
     }
   }
@@ -281,9 +282,9 @@ export function mergeOptions (
   child: Object,
   vm?: Component
 ): Object {
-  guardComponents(child)
-  guardProps(child)
-  guardDirectives(child)
+  normalizeComponents(child)
+  normalizeProps(child)
+  normalizeDirectives(child)
   if (process.env.NODE_ENV !== 'production') {
     if (child.propsData && !vm) {
       warn('propsData can only be used as an instantiation option.')

+ 0 - 0
test/unit/features/options/assets.spec.js


+ 92 - 0
test/unit/features/options/directives.spec.js

@@ -0,0 +1,92 @@
+import Vue from 'vue'
+
+describe('Options directives', () => {
+  it('basic usage', done => {
+    const bindSpy = jasmine.createSpy('bind')
+    const updateSpy = jasmine.createSpy('update')
+    const postupdateSpy = jasmine.createSpy('postupdate')
+    const unbindSpy = jasmine.createSpy('unbind')
+
+    const assertContext = (el, binding, vnode) => {
+      expect(vnode.context).toBe(vm)
+      expect(binding.arg).toBe('arg')
+      expect(binding.modifiers).toEqual({ hello: true })
+    }
+
+    const vm = new Vue({
+      template: '<div v-if="ok" v-test:arg.hello="a">{{ msg }}</div>',
+      data: {
+        msg: 'hi',
+        a: 'foo',
+        ok: true
+      },
+      directives: {
+        test: {
+          bind (el, binding, vnode) {
+            bindSpy()
+            assertContext(el, binding, vnode)
+            expect(binding.value).toBe('foo')
+            expect(binding.oldValue).toBeUndefined()
+          },
+          update (el, binding, vnode, oldVnode) {
+            updateSpy()
+            assertContext(el, binding, vnode)
+            expect(el).toBe(vm.$el)
+            expect(oldVnode).toBe(vm._vnode)
+            expect(oldVnode).not.toBe(vnode)
+            expect(binding.value).toBe('bar')
+            expect(binding.oldValue).toBe('foo')
+          },
+          postupdate (el, binding, vnode) {
+            postupdateSpy()
+            assertContext(el, binding, vnode)
+          },
+          unbind (el, binding, vnode) {
+            unbindSpy()
+            assertContext(el, binding, vnode)
+          }
+        }
+      }
+    })
+
+    vm.$mount()
+    expect(bindSpy).toHaveBeenCalled()
+    expect(updateSpy).not.toHaveBeenCalled()
+    expect(postupdateSpy).not.toHaveBeenCalled()
+    expect(unbindSpy).not.toHaveBeenCalled()
+    vm.a = 'bar'
+    waitForUpdate(() => {
+      expect(updateSpy).toHaveBeenCalled()
+      expect(postupdateSpy).toHaveBeenCalled()
+      expect(unbindSpy).not.toHaveBeenCalled()
+      vm.msg = 'bye'
+    }).then(() => {
+      expect(postupdateSpy.calls.count()).toBe(2)
+      vm.ok = false
+    }).then(() => {
+      expect(unbindSpy).toHaveBeenCalled()
+    }).then(done)
+  })
+
+  it('function shorthand', done => {
+    const spy = jasmine.createSpy('directive')
+    const vm = new Vue({
+      template: '<div v-test:arg.hello="a"></div>',
+      data: { a: 'foo' },
+      directives: {
+        test (el, binding, vnode) {
+          expect(vnode.context).toBe(vm)
+          expect(binding.arg).toBe('arg')
+          expect(binding.modifiers).toEqual({ hello: true })
+          spy(binding.value, binding.oldValue)
+        }
+      }
+    })
+    vm.$mount()
+    expect(spy).toHaveBeenCalledWith('foo', undefined)
+    vm.a = 'bar'
+    waitForUpdate(() => {
+      expect(spy).toHaveBeenCalledWith('bar', 'foo')
+    }).then(done)
+  })
+})