deprecate $set and $delete on objects, use Vue.set/delete instead

This commit is contained in:
Evan You 2015-10-03 17:09:46 -04:00
parent 26a624e61c
commit b6cceaadb1
14 changed files with 110 additions and 138 deletions

View File

@ -54,7 +54,7 @@ Vue.component('item', {
},
changeType: function () {
if (!this.isFolder) {
this.model.$set('children', [])
Vue.set(this.model, 'children', [])
this.addChild()
this.open = true
}

View File

@ -1,3 +1,4 @@
var _ = require('../util')
var Watcher = require('../watcher')
var Path = require('../parsers/path')
var textParser = require('../parsers/text')
@ -52,7 +53,7 @@ exports.$set = function (exp, val) {
*/
exports.$delete = function (key) {
this._data.$delete(key)
_.delete(this._data, key)
}
/**

View File

@ -7,6 +7,8 @@ var config = require('../config')
exports.util = _
exports.config = config
exports.set = _.set
exports.delete = _.delete
exports.nextTick = _.nextTick
/**

View File

@ -62,7 +62,7 @@ exports._initData = function () {
}
if (this._props[prop].raw !== null ||
!optionsData.hasOwnProperty(prop)) {
optionsData.$set(prop, propsData[prop])
_.set(optionsData, prop, propsData[prop])
}
}
}
@ -73,9 +73,7 @@ exports._initData = function () {
i = keys.length
while (i--) {
key = keys[i]
if (!_.isReserved(key)) {
this._proxy(key)
}
this._proxy(key)
}
// observe data
Observer.create(data, this)
@ -97,7 +95,7 @@ exports._setData = function (newData) {
i = keys.length
while (i--) {
key = keys[i]
if (!_.isReserved(key) && !(key in newData)) {
if (!(key in newData)) {
this._unproxy(key)
}
}
@ -107,7 +105,7 @@ exports._setData = function (newData) {
i = keys.length
while (i--) {
key = keys[i]
if (!this.hasOwnProperty(key) && !_.isReserved(key)) {
if (!this.hasOwnProperty(key)) {
// new property
this._proxy(key)
}
@ -125,20 +123,23 @@ exports._setData = function (newData) {
*/
exports._proxy = function (key) {
// need to store ref to self here
// because these getter/setters might
// be called by child instances!
var self = this
Object.defineProperty(self, key, {
configurable: true,
enumerable: true,
get: function proxyGetter () {
return self._data[key]
},
set: function proxySetter (val) {
self._data[key] = val
}
})
if (!_.isReserved(key)) {
// need to store ref to self here
// because these getter/setters might
// be called by child scopes via
// prototype inheritance.
var self = this
Object.defineProperty(self, key, {
configurable: true,
enumerable: true,
get: function proxyGetter () {
return self._data[key]
},
set: function proxySetter (val) {
self._data[key] = val
}
})
}
}
/**
@ -148,7 +149,9 @@ exports._proxy = function (key) {
*/
exports._unproxy = function (key) {
delete this[key]
if (!_.isReserved(key)) {
delete this[key]
}
}
/**

View File

@ -3,7 +3,6 @@ var config = require('../config')
var Dep = require('./dep')
var arrayMethods = require('./array')
var arrayKeys = Object.getOwnPropertyNames(arrayMethods)
require('./object')
/**
* Observer class that are attached to each observed

View File

@ -1,86 +0,0 @@
var _ = require('../util')
var objProto = Object.prototype
/**
* Add a new property to an observed object
* and emits corresponding event. This is internal and
* no longer exposed as of 1.0.
*
* @param {Object} obj
* @param {String} key
* @param {*} val
* @public
*/
var add = exports.add = function (obj, key, val) {
if (obj.hasOwnProperty(key)) {
return
}
if (obj._isVue) {
add(obj._data, key, val)
return
}
var ob = obj.__ob__
if (!ob || _.isReserved(key)) {
obj[key] = val
return
}
ob.convert(key, val)
ob.notify()
if (ob.vms) {
var i = ob.vms.length
while (i--) {
var vm = ob.vms[i]
vm._proxy(key)
vm._digest()
}
}
}
/**
* Set a property on an observed object, calling add to
* ensure the property is observed.
*
* @param {String} key
* @param {*} val
* @public
*/
_.define(
objProto,
'$set',
function $set (key, val) {
add(this, key, val)
this[key] = val
}
)
/**
* Deletes a property from an observed object
* and emits corresponding event
*
* @param {String} key
* @public
*/
_.define(
objProto,
'$delete',
function $delete (key) {
if (!this.hasOwnProperty(key)) return
delete this[key]
var ob = this.__ob__
if (!ob || _.isReserved(key)) {
return
}
ob.notify()
if (ob.vms) {
var i = ob.vms.length
while (i--) {
var vm = ob.vms[i]
vm._unproxy(key)
vm._digest()
}
}
}
)

View File

@ -1,5 +1,4 @@
var _ = require('../util')
var add = require('../observer/object').add
var Cache = require('../cache')
var pathCache = new Cache(1000)
var identRE = exports.identRE = /^[$_a-zA-Z]+[\w$]*$/
@ -340,7 +339,7 @@ exports.set = function (obj, path, val) {
if (process.env.NODE_ENV !== 'production' && last._isVue) {
warnNonExistent(path)
}
add(last, key, obj)
_.set(last, key, obj)
}
} else {
if (_.isArray(obj)) {
@ -351,7 +350,7 @@ exports.set = function (obj, path, val) {
if (process.env.NODE_ENV !== 'production' && obj._isVue) {
warnNonExistent(path)
}
add(obj, key, val)
_.set(obj, key, val)
}
}
}

View File

@ -1,3 +1,67 @@
/**
* Set a property on an object. Adds the new property and
* triggers change notification if the property doesn't
* already exist.
*
* @param {Object} obj
* @param {String} key
* @param {*} val
* @public
*/
exports.set = function set (obj, key, val) {
if (obj.hasOwnProperty(key)) {
obj[key] = val
return
}
if (obj._isVue) {
set(obj._data, key, val)
return
}
var ob = obj.__ob__
if (!ob) {
obj[key] = val
return
}
ob.convert(key, val)
ob.notify()
if (ob.vms) {
var i = ob.vms.length
while (i--) {
var vm = ob.vms[i]
vm._proxy(key)
vm._digest()
}
}
}
/**
* Delete a property and trigger change if necessary.
*
* @param {Object} obj
* @param {String} key
*/
exports.delete = function (obj, key) {
if (!obj.hasOwnProperty(key)) {
return
}
delete obj[key]
var ob = obj.__ob__
if (!ob) {
return
}
ob.notify()
if (ob.vms) {
var i = ob.vms.length
while (i--) {
var vm = ob.vms[i]
vm._unproxy(key)
vm._digest()
}
}
}
/**
* Check if an expression is a literal value.
*

View File

@ -26,7 +26,7 @@ function mergeData (to, from) {
toVal = to[key]
fromVal = from[key]
if (!to.hasOwnProperty(key)) {
to.$set(key, fromVal)
_.set(to, key, fromVal)
} else if (_.isObject(toVal) && _.isObject(fromVal)) {
mergeData(toVal, fromVal)
}

View File

@ -86,5 +86,5 @@ extend(p, require('./api/events'))
extend(p, require('./api/child'))
extend(p, require('./api/lifecycle'))
Vue.version = '1.0.0-alpha'
Vue.version = '1.0.0-beta.3'
module.exports = _.Vue = Vue

View File

@ -957,7 +957,7 @@ function assertObjectMutations (vm, el, done) {
)
.then(
function () {
vm.items.$set('a', {a: 3})
_.set(vm.items, 'a', {a: 3})
},
assertMarkup
)
@ -995,7 +995,7 @@ function assertObjectPrimitiveMutations (vm, el, done) {
)
.then(
function () {
vm.items.$set('a', 3)
_.set(vm.items, 'a', 3)
},
assertMarkup
)

View File

@ -219,7 +219,7 @@ describe('Misc', function () {
var test = []
var obj2 = vm.obj2
vm.$set('test', test)
obj2.$set('test', 123)
__.set(obj2, 'test', 123)
Vue.nextTick(function () {
expect(spy1).not.toHaveBeenCalled()
expect(spy2).not.toHaveBeenCalled()
@ -255,7 +255,7 @@ describe('Misc', function () {
}
})
expect(vm.$el.textContent).toBe(JSON.stringify(vm.items, null, 2))
vm.items[0].$set('a', 123)
__.set(vm.items[0], 'a', 123)
Vue.nextTick(function () {
expect(vm.$el.textContent).toBe(JSON.stringify(vm.items, null, 2) + '123')
done()

View File

@ -83,32 +83,32 @@ describe('Observer', function () {
expect(watcher.update.calls.count()).toBe(3)
})
it('observing $set/$delete', function () {
it('observing set/delete', function () {
var obj = { a: 1 }
var ob = Observer.create(obj)
var dep = ob.dep
spyOn(dep, 'notify')
obj.$set('b', 2)
_.set(obj, 'b', 2)
expect(obj.b).toBe(2)
expect(dep.notify.calls.count()).toBe(1)
obj.$delete('a')
_.delete(obj, 'a')
expect(obj.hasOwnProperty('a')).toBe(false)
expect(dep.notify.calls.count()).toBe(2)
// set existing key, should be a plain set and not
// trigger own ob's notify
obj.$set('b', 3)
_.set(obj, 'b', 3)
expect(obj.b).toBe(3)
expect(dep.notify.calls.count()).toBe(2)
// set non-existing key
obj.$set('c', 1)
_.set(obj, 'c', 1)
expect(obj.c).toBe(1)
expect(dep.notify.calls.count()).toBe(3)
// should ignore deleting non-existing key
obj.$delete('a')
_.delete(obj, 'a')
expect(dep.notify.calls.count()).toBe(3)
// should work on non-observed objects
var obj2 = { a: 1 }
obj2.$delete('a')
_.delete(obj2, 'a')
expect(obj2.hasOwnProperty('a')).toBe(false)
})
@ -166,16 +166,6 @@ describe('Observer', function () {
it('no proto', function () {
config.proto = false
// object
var obj = {a: 1}
var ob = Observer.create(obj)
expect(obj.$set).toBeTruthy()
expect(obj.$delete).toBeTruthy()
var dep = ob.dep
spyOn(dep, 'notify')
obj.$set('b', 2)
expect(dep.notify).toHaveBeenCalled()
// array
var arr = [1, 2, 3]
var ob2 = Observer.create(arr)
expect(arr.$set).toBeTruthy()

View File

@ -123,7 +123,7 @@ describe('Watcher', function () {
})
})
it('non-existent path, $set later', function (done) {
it('non-existent path, set later', function (done) {
var watcher = new Watcher(vm, 'd.e', spy)
var watcher2 = new Watcher(vm, 'b.e', spy)
expect(watcher.value).toBeUndefined()
@ -133,7 +133,7 @@ describe('Watcher', function () {
var watcher3 = new Watcher(child2, 'd.e', spy)
expect(watcher3.value).toBeUndefined()
vm.$set('d', { e: 123 })
vm.b.$set('e', 234)
_.set(vm.b, 'e', 234)
nextTick(function () {
expect(watcher.value).toBe(123)
expect(watcher2.value).toBe(234)