Skip to content

Commit 3333598

Browse files
committed
fix large array update regression (fix vuejs#1248)
1 parent 5b413fc commit 3333598

File tree

4 files changed

+62
-11
lines changed

4 files changed

+62
-11
lines changed

src/observer/array.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var arrayMethods = Object.create(arrayProto)
2828
}
2929
var result = original.apply(this, args)
3030
var ob = this.__ob__
31-
var inserted
31+
var inserted, removed
3232
switch (method) {
3333
case 'push':
3434
inserted = args
@@ -38,11 +38,17 @@ var arrayMethods = Object.create(arrayProto)
3838
break
3939
case 'splice':
4040
inserted = args.slice(2)
41+
removed = result
42+
break
43+
case 'pop':
44+
case 'shift':
45+
removed = [result]
4146
break
4247
}
4348
if (inserted) ob.observeArray(inserted)
49+
if (removed) ob.unobserveArray(removed)
4450
// notify change
45-
ob.dep.notify()
51+
ob.notify()
4652
return result
4753
})
4854
})

src/observer/index.js

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,42 @@ Observer.prototype.observe = function (val) {
111111
Observer.prototype.observeArray = function (items) {
112112
var i = items.length
113113
while (i--) {
114-
this.observe(items[i])
114+
var ob = this.observe(items[i])
115+
if (ob) {
116+
(ob.parents || (ob.parents = [])).push(this)
117+
}
118+
}
119+
}
120+
121+
/**
122+
* Remove self from the parent list of removed objects.
123+
*
124+
* @param {Array} items
125+
*/
126+
127+
Observer.prototype.unobserveArray = function (items) {
128+
var i = items.length
129+
while (i--) {
130+
var ob = items[i] && items[i].__ob__
131+
if (ob) {
132+
ob.parents.$remove(this)
133+
}
134+
}
135+
}
136+
137+
/**
138+
* Notify self dependency, and also parent Array dependency
139+
* if any.
140+
*/
141+
142+
Observer.prototype.notify = function () {
143+
this.dep.notify()
144+
var parents = this.parents
145+
if (parents) {
146+
var i = parents.length
147+
while (i--) {
148+
parents[i].notify()
149+
}
115150
}
116151
}
117152

@@ -136,12 +171,6 @@ Observer.prototype.convert = function (key, val) {
136171
if (childOb) {
137172
childOb.dep.depend()
138173
}
139-
if (_.isArray(val)) {
140-
for (var e, i = 0, l = val.length; i < l; i++) {
141-
e = val[i]
142-
e && e.__ob__ && e.__ob__.dep.depend()
143-
}
144-
}
145174
}
146175
return val
147176
},

src/observer/object.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ _.define(
2121
return
2222
}
2323
ob.convert(key, val)
24-
ob.dep.notify()
24+
ob.notify()
2525
if (ob.vms) {
2626
var i = ob.vms.length
2727
while (i--) {
@@ -69,7 +69,7 @@ _.define(
6969
if (!ob || _.isReserved(key)) {
7070
return
7171
}
72-
ob.dep.notify()
72+
ob.notify()
7373
if (ob.vms) {
7474
var i = ob.vms.length
7575
while (i--) {

test/unit/specs/misc_spec.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,4 +332,20 @@ describe('Misc', function () {
332332
Vue.config.strict = false
333333
})
334334

335+
it('nested object $set should trigger parent array notify', function (done) {
336+
var vm = new Vue({
337+
el: document.createElement('div'),
338+
template: '{{items | json}}{{items[0].a}}',
339+
data: {
340+
items: [{}]
341+
}
342+
})
343+
expect(vm.$el.textContent).toBe(JSON.stringify(vm.items, null, 2))
344+
vm.items[0].$set('a', 123)
345+
Vue.nextTick(function () {
346+
expect(vm.$el.textContent).toBe(JSON.stringify(vm.items, null, 2) + '123')
347+
done()
348+
})
349+
})
350+
335351
})

0 commit comments

Comments
 (0)