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

expose Vue.set/delete on instances as vm.$set/$delete

Evan You 9 лет назад
Родитель
Сommit
1e74675053

+ 2 - 0
flow/component.js

@@ -32,6 +32,8 @@ declare interface Component {
   $mount: (el?: Element | string, hydrating?: boolean) => Component;
   $forceUpdate: () => void;
   $destroy: () => void;
+  $set: (obj: Array<any> | Object, key: any, val: any) => void;
+  $delete: (obj: Object, key: string) => void;
   $watch: (expOrFn: string | Function, cb: Function, options?: Object) => Function;
   $on: (event: string, fn: Function) => Component;
   $once: (event: string, fn: Function) => Component;

+ 5 - 0
src/core/instance/state.js

@@ -4,6 +4,8 @@ import Watcher from '../observer/watcher'
 import Dep from '../observer/dep'
 
 import {
+  set,
+  del,
   observe,
   defineReactive,
   observerState
@@ -192,6 +194,9 @@ export function stateMixin (Vue: Class<Component>) {
   }
   Object.defineProperty(Vue.prototype, '$data', dataDef)
 
+  Vue.prototype.$set = set
+  Vue.prototype.$delete = del
+
   Vue.prototype.$watch = function (
     expOrFn: string | Function,
     cb: Function,

+ 89 - 0
test/unit/features/instance/methods-data.spec.js

@@ -0,0 +1,89 @@
+import Vue from 'vue'
+
+describe('Instance methods data', () => {
+  it('$set/$delete', done => {
+    const vm = new Vue({
+      template: '<div>{{ a.msg }}</div>',
+      data: {
+        a: {}
+      }
+    }).$mount()
+    expect(vm.$el.innerHTML).toBe('')
+    vm.$set(vm.a, 'msg', 'hello')
+    waitForUpdate(() => {
+      expect(vm.$el.innerHTML).toBe('hello')
+      vm.$delete(vm.a, 'msg')
+    }).then(() => {
+      expect(vm.$el.innerHTML).toBe('')
+    }).then(done)
+  })
+
+  describe('$watch', () => {
+    let vm, spy
+    beforeEach(() => {
+      vm = new Vue({
+        data: {
+          a: {
+            b: 1
+          }
+        }
+      })
+      spy = jasmine.createSpy('watch')
+    })
+
+    it('basic usage', done => {
+      vm.$watch('a.b', spy)
+      vm.a.b = 2
+      waitForUpdate(() => {
+        expect(spy.calls.count()).toBe(1)
+        expect(spy).toHaveBeenCalledWith(2, 1)
+        vm.a = { b: 3 }
+      }).then(() => {
+        expect(spy.calls.count()).toBe(2)
+        expect(spy).toHaveBeenCalledWith(3, 2)
+      }).then(done)
+    })
+
+    it('immediate', () => {
+      vm.$watch('a.b', spy, { immediate: true })
+      expect(spy.calls.count()).toBe(1)
+      expect(spy).toHaveBeenCalledWith(1)
+    })
+
+    it('unwatch', done => {
+      const unwatch = vm.$watch('a.b', spy)
+      unwatch()
+      vm.a.b = 2
+      waitForUpdate(() => {
+        expect(spy.calls.count()).toBe(0)
+      }).then(done)
+    })
+
+    it('function watch', done => {
+      vm.$watch(function () {
+        return this.a.b
+      }, spy)
+      vm.a.b = 2
+      waitForUpdate(() => {
+        expect(spy).toHaveBeenCalledWith(2, 1)
+      }).then(done)
+    })
+
+    it('deep watch', done => {
+      var oldA = vm.a
+      vm.$watch('a', spy, { deep: true })
+      vm.a.b = 2
+      waitForUpdate(() => {
+        expect(spy).toHaveBeenCalledWith(oldA, oldA)
+        vm.a = { b: 3 }
+      }).then(() => {
+        expect(spy).toHaveBeenCalledWith(vm.a, oldA)
+      }).then(done)
+    })
+
+    it('warn expresssion', () => {
+      vm.$watch('a + b', spy)
+      expect('Watcher only accepts simple dot-delimited paths').toHaveBeenWarned()
+    })
+  })
+})

+ 0 - 70
test/unit/features/instance/methods-watch.spec.js

@@ -1,70 +0,0 @@
-import Vue from 'vue'
-
-describe('Instance methods watch', () => {
-  let vm, spy
-  beforeEach(() => {
-    vm = new Vue({
-      data: {
-        a: {
-          b: 1
-        }
-      }
-    })
-    spy = jasmine.createSpy('watch')
-  })
-
-  it('basic usage', done => {
-    vm.$watch('a.b', spy)
-    vm.a.b = 2
-    waitForUpdate(() => {
-      expect(spy.calls.count()).toBe(1)
-      expect(spy).toHaveBeenCalledWith(2, 1)
-      vm.a = { b: 3 }
-    }).then(() => {
-      expect(spy.calls.count()).toBe(2)
-      expect(spy).toHaveBeenCalledWith(3, 2)
-    }).then(done)
-  })
-
-  it('immediate', () => {
-    vm.$watch('a.b', spy, { immediate: true })
-    expect(spy.calls.count()).toBe(1)
-    expect(spy).toHaveBeenCalledWith(1)
-  })
-
-  it('unwatch', done => {
-    const unwatch = vm.$watch('a.b', spy)
-    unwatch()
-    vm.a.b = 2
-    waitForUpdate(() => {
-      expect(spy.calls.count()).toBe(0)
-    }).then(done)
-  })
-
-  it('function watch', done => {
-    vm.$watch(function () {
-      return this.a.b
-    }, spy)
-    vm.a.b = 2
-    waitForUpdate(() => {
-      expect(spy).toHaveBeenCalledWith(2, 1)
-    }).then(done)
-  })
-
-  it('deep watch', done => {
-    var oldA = vm.a
-    vm.$watch('a', spy, { deep: true })
-    vm.a.b = 2
-    waitForUpdate(() => {
-      expect(spy).toHaveBeenCalledWith(oldA, oldA)
-      vm.a = { b: 3 }
-    }).then(() => {
-      expect(spy).toHaveBeenCalledWith(vm.a, oldA)
-    }).then(done)
-  })
-
-  it('warn expresssion', () => {
-    vm.$watch('a + b', spy)
-    expect('Watcher only accepts simple dot-delimited paths').toHaveBeenWarned()
-  })
-})