Skip to content

Commit

Permalink
improve v-bind implementation and make it work on components (fix vue…
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Sep 14, 2016
1 parent 2b588b7 commit d6a7568
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 44 deletions.
4 changes: 1 addition & 3 deletions flow/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ declare type ASTElementHandlers = {
[key: string]: ASTElementHandler | Array<ASTElementHandler>;
}

declare type ASTElementHooks = { [key: string]: Array<string> }

declare type ASTDirective = {
name: string;
value: string;
Expand Down Expand Up @@ -106,7 +104,6 @@ declare type ASTElement = {
staticClass?: string;
classBinding?: string;
styleBinding?: string;
hooks?: ASTElementHooks;
events?: ASTElementHandlers;
nativeEvents?: ASTElementHandlers;

Expand All @@ -117,6 +114,7 @@ declare type ASTElement = {

forbidden?: true;
once?: true;
wrapData?: (code: string) => string;
}

declare type ASTExpression = {
Expand Down
2 changes: 1 addition & 1 deletion flow/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ declare interface Component {
// renderSlot
_t: (name: string, fallback: ?Array<VNode>) => ?Array<VNode>;
// apply v-bind object
_b: (vnode: VNodeWithData, value: any) => void;
_b: (data: any, value: any, asProp?: boolean) => VNodeData;
// retrive custom keyCode
_k: (key: string) => ?number;

Expand Down
19 changes: 6 additions & 13 deletions src/compiler/codegen/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,6 @@ function genData (el: ASTElement): string | void {
if (el.props) {
data += `domProps:{${genProps(el.props)}},`
}
// hooks
if (el.hooks) {
data += `hook:{${genHooks(el.hooks)}},`
}
// event handlers
if (el.events) {
data += `${genHandlers(el.events)},`
Expand All @@ -166,7 +162,12 @@ function genData (el: ASTElement): string | void {
}]}`
}
}
return data.replace(/,$/, '') + '}'
data = data.replace(/,$/, '') + '}'
// v-bind data wrap
if (el.wrapData) {
data = el.wrapData(data)
}
return data
}

function genDirectives (el: ASTElement): string | void {
Expand Down Expand Up @@ -243,11 +244,3 @@ function genProps (props: Array<{ name: string, value: string }>): string {
}
return res.slice(0, -1)
}

function genHooks (hooks: { [key: string]: Array<string> }): string {
let res = ''
for (const key in hooks) {
res += `"${key}":function(n1,n2){${hooks[key].join(';')}},`
}
return res.slice(0, -1)
}
14 changes: 9 additions & 5 deletions src/compiler/directives/bind.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
/* @flow */

import { addHook } from '../helpers'

export default function bind (el: ASTElement, dir: ASTDirective) {
addHook(el, 'construct', `_b(n1,${dir.value}${
dir.modifiers && dir.modifiers.prop ? ',true' : ''
})`)
el.wrapData = (code: string) => {
return `_b(${
code
},${
dir.value
}${
dir.modifiers && dir.modifiers.prop ? ',true' : ''
})`
}
}
11 changes: 0 additions & 11 deletions src/compiler/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,6 @@ export function addDirective (
(el.directives || (el.directives = [])).push({ name, value, arg, modifiers })
}

export function addHook (el: ASTElement, name: string, code: string) {
const hooks = el.hooks || (el.hooks = {})
const hook = hooks[name]
/* istanbul ignore if */
if (hook) {
hook.push(code)
} else {
hooks[name] = [code]
}
}

export function addHandler (
el: ASTElement,
name: string,
Expand Down
7 changes: 4 additions & 3 deletions src/core/instance/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,10 @@ export function renderMixin (Vue: Class<Component>) {

// apply v-bind object
Vue.prototype._b = function bindProps (
vnode: VNodeWithData,
data: any,
value: any,
asProp?: boolean) {
asProp?: boolean
): VNodeData {
if (value) {
if (!isObject(value)) {
process.env.NODE_ENV !== 'production' && warn(
Expand All @@ -188,7 +189,6 @@ export function renderMixin (Vue: Class<Component>) {
if (Array.isArray(value)) {
value = toObject(value)
}
const data: any = vnode.data
for (const key in value) {
if (key === 'class' || key === 'style') {
data[key] = value[key]
Expand All @@ -201,6 +201,7 @@ export function renderMixin (Vue: Class<Component>) {
}
}
}
return data
}

// expose v-on keyCodes
Expand Down
7 changes: 0 additions & 7 deletions src/core/vdom/vnode.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,6 @@ export default class VNode {
this.isRootInsert = true
this.isComment = false
this.isCloned = false
// apply construct hook.
// this is applied during render, before patch happens.
// unlike other hooks, this is applied on both client and server.
const constructHook = data && data.hook && data.hook.construct
if (constructHook) {
constructHook(this)
}
}
}

Expand Down
13 changes: 13 additions & 0 deletions test/unit/features/options/props.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,19 @@ describe('Options props', () => {
})
})

it('should work with v-bind', () => {
const vm = new Vue({
template: `<test v-bind="{ a: 1, b: 2 }"></test>`,
components: {
test: {
props: ['a', 'b'],
template: '<div>{{ a }} {{ b }}</div>'
}
}
}).$mount()
expect(vm.$el.textContent).toBe('1 2')
})

it('should warn data fields already defined as a prop', () => {
new Vue({
template: '<test a="1"></test>',
Expand Down
2 changes: 1 addition & 1 deletion test/unit/modules/compiler/codegen.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ describe('codegen', () => {
it('generate v-bind directive', () => {
assertCodegen(
'<p v-bind="test"></p>',
`with(this){return _h('p',{hook:{"construct":function(n1,n2){_b(n1,test)}}})}`
`with(this){return _h('p',_b({},test))}`
)
})

Expand Down

0 comments on commit d6a7568

Please sign in to comment.