Browse Source

feat: support sync modifier for v-bind="object" (#5943)

close #5937
dev
wenlu.wang 8 years ago
committed by Evan You
parent
commit
3965e5053a
  1. 2
      flow/component.js
  2. 6
      src/compiler/directives/bind.js
  3. 10
      src/core/instance/render-helpers/bind-object-props.js
  4. 30
      test/unit/features/directives/bind.spec.js
  5. 16
      test/unit/modules/compiler/codegen.spec.js

2
flow/component.js

@ -120,7 +120,7 @@ declare interface Component {
// renderSlot
_t: (name: string, fallback: ?Array<VNode>, props: ?Object) => ?Array<VNode>;
// apply v-bind object
_b: (data: any, value: any, asProp?: boolean) => VNodeData;
_b: (data: any, tag: string, value: any, asProp: boolean, isSync?: boolean) => VNodeData;
// check custom keyCode
_k: (eventKeyCode: number, key: string, builtInAlias: number | Array<number> | void) => boolean;
// resolve scoped slots

6
src/compiler/directives/bind.js

@ -2,8 +2,10 @@
export default function bind (el: ASTElement, dir: ASTDirective) {
el.wrapData = (code: string) => {
return `_b(${code},'${el.tag}',${dir.value}${
dir.modifiers && dir.modifiers.prop ? ',true' : ''
return `_b(${code},'${el.tag}',${dir.value},${
dir.modifiers && dir.modifiers.prop ? 'true' : 'false'
}${
dir.modifiers && dir.modifiers.sync ? ',true' : ''
})`
}
}

10
src/core/instance/render-helpers/bind-object-props.js

@ -16,7 +16,8 @@ export function bindObjectProps (
data: any,
tag: string,
value: any,
asProp?: boolean
asProp: boolean,
isSync?: boolean
): VNodeData {
if (value) {
if (!isObject(value)) {
@ -44,6 +45,13 @@ export function bindObjectProps (
}
if (!(key in hash)) {
hash[key] = value[key]
if (isSync) {
const on = data.on || (data.on = {})
on[`update:${key}`] = function ($event) {
value[key] = $event
}
}
}
}
}

30
test/unit/features/directives/bind.spec.js

@ -187,6 +187,36 @@ describe('Directive v-bind', () => {
}).then(done)
})
it('.sync modifier with bind object', done => {
const vm = new Vue({
template: `<test v-bind.sync="test"/>`,
data: {
test: {
fooBar: 1
}
},
components: {
test: {
props: ['fooBar'],
template: `<div @click="handleUpdate">{{ fooBar }}</div>`,
methods: {
handleUpdate () {
this.$emit('update:fooBar', 2)
}
}
}
}
}).$mount()
expect(vm.$el.textContent).toBe('1')
triggerEvent(vm.$el, 'click')
waitForUpdate(() => {
expect(vm.$el.textContent).toBe('2')
vm.test.fooBar = 3
}).then(() => {
expect(vm.$el.textContent).toBe('3')
}).then(done)
})
it('bind object with overwrite', done => {
const vm = new Vue({
template: '<input v-bind="test" id="foo" :class="test.value">',

16
test/unit/modules/compiler/codegen.spec.js

@ -126,7 +126,21 @@ describe('codegen', () => {
it('generate v-bind directive', () => {
assertCodegen(
'<p v-bind="test"></p>',
`with(this){return _c('p',_b({},'p',test))}`
`with(this){return _c('p',_b({},'p',test,false))}`
)
})
it('generate v-bind with prop directive', () => {
assertCodegen(
'<p v-bind.prop="test"></p>',
`with(this){return _c('p',_b({},'p',test,true))}`
)
})
it('generate v-bind directive with sync modifier', () => {
assertCodegen(
'<p v-bind.sync="test"></p>',
`with(this){return _c('p',_b({},'p',test,false,true))}`
)
})

Loading…
Cancel
Save