Skip to content

Commit

Permalink
feat: support sync modifier for v-bind="object" (#5943)
Browse files Browse the repository at this point in the history
close #5937
  • Loading branch information
Kingwl authored and yyx990803 committed Jun 30, 2017
1 parent bd79d7e commit 3965e50
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 5 deletions.
2 changes: 1 addition & 1 deletion flow/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions src/compiler/directives/bind.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 9 additions & 1 deletion src/core/instance/render-helpers/bind-object-props.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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
}
}
}
}
}
Expand Down
30 changes: 30 additions & 0 deletions test/unit/features/directives/bind.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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">',
Expand Down
16 changes: 15 additions & 1 deletion test/unit/modules/compiler/codegen.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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))}`
)
})

Expand Down

0 comments on commit 3965e50

Please sign in to comment.