Skip to content

Commit 1e575a7

Browse files
committed
v-bind should be in deep mode when used on objects for class, style and attributes
1 parent dd70770 commit 1e575a7

File tree

4 files changed

+46
-11
lines changed

4 files changed

+46
-11
lines changed

src/directives/internal/class.js

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ var removeClass = _.removeClass
44

55
module.exports = {
66

7+
deep: true,
8+
79
update: function (value) {
810
if (value && typeof value === 'string') {
911
this.handleObject(stringToObject(value))

src/directives/public/bind.js

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ module.exports = {
3030
bind: function () {
3131
var attr = this.arg
3232
var tag = this.el.tagName
33+
// should be deep watch on object mode
34+
if (!attr) {
35+
this.deep = true
36+
}
3337
// handle interpolation bindings
3438
if (this.descriptor.interp) {
3539
// only allow binding on native attributes

src/watcher.js

+10-11
Original file line numberDiff line numberDiff line change
@@ -325,19 +325,18 @@ Watcher.prototype.teardown = function () {
325325
* getters, so that every nested property inside the object
326326
* is collected as a "deep" dependency.
327327
*
328-
* @param {Object} obj
328+
* @param {*} val
329329
*/
330330

331-
function traverse (obj) {
332-
var key, val, i
333-
for (key in obj) {
334-
val = obj[key]
335-
if (_.isArray(val)) {
336-
i = val.length
337-
while (i--) traverse(val[i])
338-
} else if (_.isObject(val)) {
339-
traverse(val)
340-
}
331+
function traverse (val) {
332+
var i, keys
333+
if (_.isArray(val)) {
334+
i = val.length
335+
while (i--) traverse(val[i])
336+
} else if (_.isObject(val)) {
337+
keys = Object.keys(val)
338+
i = keys.length
339+
while (i--) traverse(val[keys[i]])
341340
}
342341
}
343342

test/unit/specs/misc_spec.js

+30
Original file line numberDiff line numberDiff line change
@@ -313,4 +313,34 @@ describe('Misc', function () {
313313
}
314314
})
315315
})
316+
317+
it('deep watch for class, style and bind', function (done) {
318+
var el = document.createElement('div')
319+
var vm = new Vue({
320+
el: el,
321+
template: '<div :class="classes" :style="styles" v-bind="attrs"></div>',
322+
data: {
323+
classes: { a: true, b: false },
324+
styles: { color: 'red', fontSize: '14px' },
325+
attrs: { a: 1, b: 2 }
326+
}
327+
})
328+
var div = el.firstChild
329+
expect(div.className).toBe('a')
330+
expect(div.style.color).toBe('red')
331+
expect(div.style.fontSize).toBe('14px')
332+
expect(div.getAttribute('a')).toBe('1')
333+
expect(div.getAttribute('b')).toBe('2')
334+
vm.classes.b = true
335+
vm.styles.color = 'green'
336+
vm.attrs.a = 3
337+
Vue.nextTick(function () {
338+
expect(div.className).toBe('a b')
339+
expect(div.style.color).toBe('green')
340+
expect(div.style.fontSize).toBe('14px')
341+
expect(div.getAttribute('a')).toBe('3')
342+
expect(div.getAttribute('b')).toBe('2')
343+
done()
344+
})
345+
})
316346
})

0 commit comments

Comments
 (0)