Added support for properties which were created with defineProperty outside of vue

This commit is contained in:
Justin Berger 2015-11-07 17:23:53 -07:00
parent 6ce6e0c995
commit 0b1be55c04
2 changed files with 84 additions and 7 deletions

View File

@ -172,7 +172,11 @@ function copyAugment (target, src, keys) {
function defineReactive (obj, key, val) {
var dep = new Dep()
var childOb = Observer.create(val)
var property = Object.getOwnPropertyDescriptor(obj, key)
var getter = (property && property.get) || function () { return val }
var setter = (property && property.set) || function (v) { val = v }
var childOb = Observer.create(getter())
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
@ -182,18 +186,18 @@ function defineReactive (obj, key, val) {
if (childOb) {
childOb.dep.depend()
}
if (_.isArray(val)) {
for (var e, i = 0, l = val.length; i < l; i++) {
e = val[i]
if (_.isArray(getter())) {
for (var e, i = 0, l = getter().length; i < l; i++) {
e = getter()[i]
e && e.__ob__ && e.__ob__.dep.depend()
}
}
}
return val
return getter()
},
set: function metaSetter (newVal) {
if (newVal === val) return
val = newVal
if (newVal === getter()) return
setter(newVal)
childOb = Observer.create(newVal)
dep.notify()
}

View File

@ -38,6 +38,35 @@ describe('Observer', function () {
expect(ob2).toBe(ob)
})
it('create on already observed object', function () {
// on object
var obj = {}
var val = 0
Object.defineProperty(obj, 'a', {
configurable: true,
enumerable: true,
get: function () {
return val
},
set: function (v) {
val = v
}
})
var ob = Observer.create(obj)
expect(ob instanceof Observer).toBe(true)
expect(ob.value).toBe(obj)
expect(obj.__ob__).toBe(ob)
// should return existing ob on already observed objects
var ob2 = Observer.create(obj)
expect(ob2).toBe(ob)
// should call underlying setter
obj.a = 10
expect(val).toBe(10)
})
it('create on array', function () {
// on object
var arr = [{}, {}]
@ -82,6 +111,50 @@ describe('Observer', function () {
expect(watcher.update.calls.count()).toBe(3)
})
it('observing object prop change on defined property', function () {
var obj = { }
var val = { b: 2 }
Object.defineProperty(obj, 'a', {
configurable: true,
enumerable: true,
get: function () {
return val
},
set: function (v) {
val = v
}
})
Observer.create(obj)
// mock a watcher!
var watcher = {
deps: [],
addDep: function (dep) {
this.deps.push(dep)
dep.addSub(this)
},
update: jasmine.createSpy()
}
// collect dep
Dep.target = watcher
obj.a.b
Dep.target = null
expect(watcher.deps.length).toBe(3) // obj.a + a.b + b
obj.a.b = 3
expect(watcher.update.calls.count()).toBe(1)
// swap object
obj.a = { b: 4 }
expect(watcher.update.calls.count()).toBe(2)
watcher.deps = []
Dep.target = watcher
obj.a.b
Dep.target = null
expect(watcher.deps.length).toBe(3)
// set on the swapped object
obj.a.b = 5
expect(watcher.update.calls.count()).toBe(3)
})
it('observing set/delete', function () {
var obj = { a: 1 }
var ob = Observer.create(obj)