Skip to content

Commit 59cf0cc

Browse files
committed
only sync $value change inside v-repeat back to original array for primitive values (fix #853)
1 parent b6e9e64 commit 59cf0cc

File tree

9 files changed

+61
-42
lines changed

9 files changed

+61
-42
lines changed

src/directive.js

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -203,23 +203,31 @@ p._teardown = function () {
203203
* e.g. v-model.
204204
*
205205
* @param {*} value
206-
* @param {Boolean} lock - prevent wrtie triggering update.
207206
* @public
208207
*/
209208

210-
p.set = function (value, lock) {
209+
p.set = function (value) {
211210
if (this.twoWay) {
212-
if (lock) {
213-
this._locked = true
214-
}
215-
this._watcher.set(value)
216-
if (lock) {
217-
var self = this
218-
_.nextTick(function () {
219-
self._locked = false
220-
})
221-
}
211+
this._withLock(function () {
212+
this._watcher.set(value)
213+
})
222214
}
223215
}
224216

217+
/**
218+
* Execute a function while preventing that function from
219+
* triggering updates on this directive instance.
220+
*
221+
* @param {Function} fn
222+
*/
223+
224+
p._withLock = function (fn) {
225+
var self = this
226+
self._locked = true
227+
fn.call(self)
228+
_.nextTick(function () {
229+
self._locked = false
230+
})
231+
}
232+
225233
module.exports = Directive

src/directives/model/checkbox.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module.exports = {
66
var self = this
77
var el = this.el
88
this.listener = function () {
9-
self.set(el.checked, true)
9+
self.set(el.checked)
1010
}
1111
_.on(el, 'change', this.listener)
1212
if (el.checked) {

src/directives/model/default.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ module.exports = {
3232

3333
// shared setter
3434
function set () {
35-
self.set(
36-
number ? _.toNumber(el.value) : el.value,
37-
true
38-
)
35+
var val = number
36+
? _.toNumber(el.value)
37+
: el.value
38+
self.set(val)
3939
}
4040

4141
// if the directive has filters, we need to

src/directives/model/radio.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module.exports = {
66
var self = this
77
var el = this.el
88
this.listener = function () {
9-
self.set(el.value, true)
9+
self.set(el.value)
1010
}
1111
_.on(el, 'change', this.listener)
1212
if (el.checked) {

src/directives/model/select.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ module.exports = {
2323
? value.map(_.toNumber)
2424
: _.toNumber(value)
2525
: value
26-
self.set(value, true)
26+
self.set(value)
2727
}
2828
_.on(el, 'change', this.listener)
2929
checkInitialValue.call(this)

src/directives/repeat.js

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,10 @@ module.exports = {
288288
}
289289
} else { // new instance
290290
vm = this.build(obj, i, true)
291-
vm._new = true
291+
// the _new flag is used in the second pass for
292+
// vm cache retrival, but if this is the init phase
293+
// the flag can just be set to false directly.
294+
vm._new = !init
292295
vm._reused = false
293296
}
294297
vms[i] = vm
@@ -395,16 +398,20 @@ module.exports = {
395398
if (needCache) {
396399
this.cacheVm(raw, vm, this.converted ? meta.$key : null)
397400
}
398-
// sync back changes for $value, particularly for
399-
// two-way bindings of primitive values
400-
var self = this
401-
vm.$watch('$value', function (val) {
402-
if (self.converted) {
403-
self.rawValue[vm.$key] = val
404-
} else {
405-
self.rawValue.$set(vm.$index, val)
406-
}
407-
})
401+
// sync back changes for two-way bindings of primitive values
402+
var type = typeof raw
403+
if (type === 'string' || type === 'number') {
404+
var dir = this
405+
vm.$watch(alias || '$value', function (val) {
406+
dir._withLock(function () {
407+
if (dir.converted) {
408+
dir.rawValue[vm.$key] = val
409+
} else {
410+
dir.rawValue.$set(vm.$index, val)
411+
}
412+
})
413+
})
414+
}
408415
return vm
409416
},
410417

src/filters/array-filters.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,19 @@ exports.orderBy = function (arr, sortKey, reverseKey) {
7979
*/
8080

8181
function contains (val, search) {
82-
if (_.isObject(val)) {
82+
if (_.isPlainObject(val)) {
8383
for (var key in val) {
8484
if (contains(val[key], search)) {
8585
return true
8686
}
8787
}
88+
} else if (_.isArray(val)) {
89+
var i = val.length
90+
while (i--) {
91+
if (contains(val[i], search)) {
92+
return true
93+
}
94+
}
8895
} else if (val != null) {
8996
return val.toString().toLowerCase().indexOf(search) > -1
9097
}

test/unit/specs/directive_spec.js

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -136,16 +136,9 @@ describe('Directive', function () {
136136
d.set(2)
137137
expect(vm.a).toBe(6)
138138
nextTick(function () {
139-
expect(def.update.calls.count()).toBe(2)
140-
expect(def.update).toHaveBeenCalledWith(6, 1)
141-
// locked set
142-
d.set(3, true)
143-
expect(vm.a).toBe(9)
144-
nextTick(function () {
145-
// should have no update calls
146-
expect(def.update.calls.count()).toBe(2)
147-
done()
148-
})
139+
// should have no update calls
140+
expect(def.update.calls.count()).toBe(1)
141+
done()
149142
})
150143
})
151144

test/unit/specs/filters/filters_spec.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ describe('Filters', function () {
100100
var arr = [
101101
{ a: 1, b: { c: 'hello' }},
102102
{ a: 2, b: 'hello'},
103-
{ a: 3, b: 2 }
103+
{ a: 3, b: ['yoyo'] }
104104
]
105105
var vm = new Vue({
106106
data: {
@@ -135,6 +135,10 @@ describe('Filters', function () {
135135
// number search key
136136
res = filter.call(vm, arr, 'search.n')
137137
expect(res[0]).toBe(arr[1])
138+
// search in sub array
139+
res = filter.call(vm, arr, "'yoyo'")
140+
expect(res.length).toBe(1)
141+
expect(res[0]).toBe(arr[2])
138142
})
139143

140144
it('orderBy', function () {

0 commit comments

Comments
 (0)