Browse Source

merge renderElement and renderElementWithChildren

dev
Evan You 9 years ago
parent
commit
1b3b19491f
  1. 14
      src/compiler/codegen.js
  2. 40
      src/core/instance/render.js
  3. 37
      src/core/vdom/create-component.js
  4. 61
      src/core/vdom/create-element.js
  5. 3
      src/core/vdom/helpers.js
  6. 6
      src/core/vdom/vnode.js
  7. 4
      src/platforms/web/compiler/modules/transition.js
  8. 90
      test/unit/modules/compiler/codegen.spec.js
  9. 76
      test/unit/modules/vdom/create-element.spec.js

14
src/compiler/codegen.js

@ -30,7 +30,7 @@ export function generate (
dataGenFns = pluckModuleFunction(options.modules, 'genData')
platformDirectives = options.directives || {}
isPlatformReservedTag = options.isReservedTag || no
const code = ast ? genElement(ast) : '_h(_e("div"))'
const code = ast ? genElement(ast) : '_h("div")'
staticRenderFns = prevStaticRenderFns
return {
render: `with(this){return ${code}}`,
@ -64,12 +64,12 @@ function genElement (el: ASTElement): string {
const children = !el.inlineTemplate
? genChildren(el, !el.ns && !isPlatformReservedTag(el.tag) /* asThunk */)
: null
code = `_h(_e('${el.tag}'${
data ? `,${data}` : el.ns ? ',void 0' : '' // data
code = `_h('${el.tag}'${
data ? `,${data}` : (children || el.ns) ? ',void 0' : '' // data
}${
el.ns ? `,'${el.ns}'` : '' // namespace
})${
children ? `,${children}` : '' // children
}${
el.ns ? `,'${el.ns}'` : '' // namespace
})`
}
// module transforms
@ -78,7 +78,7 @@ function genElement (el: ASTElement): string {
}
// check keep-alive
if (el.component && el.keepAlive) {
code = `_h(_e("KeepAlive",{props:{child:${code}}}))`
code = `_h("KeepAlive",{props:{child:${code}}})`
}
return code
}
@ -253,7 +253,7 @@ function genSlot (el: ASTElement): string {
function genComponent (el: ASTElement): string {
const children = genChildren(el, true)
return `_h(_e(${el.component},${genData(el)})${
return `_h(${el.component},${genData(el)}${
children ? `,${children}` : ''
})`
}

40
src/core/instance/render.js

@ -8,11 +8,7 @@ import {
nextTick, resolveAsset, _toString, toNumber
} from '../util/index'
import {
renderElement,
renderElementWithChildren,
renderStatic
} from '../vdom/create-element'
import { createElement } from '../vdom/create-element'
export const renderState: {
activeInstance: ?Component
@ -26,14 +22,7 @@ export function initRender (vm: Component) {
vm.$slots = {}
// bind the public createElement fn to this instance
// so that we get proper render context inside it.
vm.$createElement = bind(function (
tag?: string | Class<Component> | Function | Object,
data?: VNodeData,
children?: VNodeChildren,
namespace?: string
) {
return this._h(this._e(tag, data, namespace), children)
}, vm)
vm.$createElement = bind(createElement, vm)
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
@ -88,22 +77,29 @@ export function renderMixin (Vue: Class<Component>) {
}
// shorthands used in render functions
Vue.prototype._h = renderElementWithChildren
Vue.prototype._e = renderElement
Vue.prototype._m = renderStatic
Vue.prototype._h = createElement
// toString for mustaches
Vue.prototype._s = _toString
// number conversion
Vue.prototype._n = toNumber
//
Vue.prototype._m = function renderStatic (index?: number): Object | void {
return this._staticTrees[index] || (
this._staticTrees[index] = this.$options.staticRenderFns[index].call(
this._renderProxy
)
)
}
// filter resolution helper
const identity = _ => _
Vue.prototype._f = function (id) {
Vue.prototype._f = function resolveFilter (id) {
return resolveAsset(this.$options, 'filters', id, true) || identity
}
// render v-for
Vue.prototype._l = function (
Vue.prototype._l = function renderList (
val: any,
render: () => VNode
): ?Array<VNode> {
@ -130,7 +126,7 @@ export function renderMixin (Vue: Class<Component>) {
}
// apply v-bind object
Vue.prototype._b = function (vnode: VNodeWithData, value: any) {
Vue.prototype._b = function bindProps (vnode: VNodeWithData, value: any) {
if (value) {
if (!isObject(value)) {
process.env.NODE_ENV !== 'production' && warn(
@ -153,7 +149,9 @@ export function renderMixin (Vue: Class<Component>) {
}
// expose v-on keyCodes
Vue.prototype._k = key => config.keyCodes[key]
Vue.prototype._k = function getKeyCodes (key: string): any {
return config.keyCodes[key]
}
}
function resolveSlots (
@ -161,7 +159,7 @@ function resolveSlots (
renderChildren: Array<any> | () => Array<any> | string
) {
if (renderChildren) {
const children = normalizeChildren(renderChildren)
const children = normalizeChildren(renderChildren) || []
const slots = {}
const defaultSlot = []
let name, child

37
src/core/vdom/create-component.js

@ -2,6 +2,7 @@
import Vue from '../instance/index'
import VNode from './vnode'
import { normalizeChildren } from './helpers'
import { callHook } from '../instance/lifecycle'
import { warn, isObject, hasOwn, hyphenate } from '../util/index'
@ -14,14 +15,27 @@ export function createComponent (
parent: Component,
context: Component,
host: ?Component,
children?: VNodeChildren,
tag?: string
): VNode | void {
// ensure children is a thunk
if (process.env.NODE_ENV !== 'production' &&
children && typeof children !== 'function') {
warn(
'A component\'s children should be a function that returns the ' +
'children array. This allows the component to track the children ' +
'dependencies and optimizes re-rendering.'
)
}
if (!Ctor) {
return
}
if (isObject(Ctor)) {
Ctor = Vue.extend(Ctor)
}
if (typeof Ctor !== 'function') {
if (process.env.NODE_ENV !== 'production') {
warn(`Invalid Component definition: ${Ctor}`, parent)
@ -50,15 +64,22 @@ export function createComponent (
data = data || {}
// merge component management hooks onto the placeholder node
// only need to do this if this is not a functional component
if (!Ctor.options.functional) {
mergeHooks(data)
}
// extract props
const propsData = extractProps(data, Ctor)
// functional component
if (Ctor.options.functional) {
return Ctor.options.render.call(
null,
parent.$createElement, // h
propsData || {}, // props
normalizeChildren(children) // children
)
}
// merge component management hooks onto the placeholder node
mergeHooks(data)
// extract listeners, since these needs to be treated as
// child component listeners instead of DOM listeners
const listeners = data.on
@ -71,9 +92,7 @@ export function createComponent (
const vnode = new VNode(
`vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,
data, undefined, undefined, undefined, undefined, context, host,
{ Ctor, propsData, listeners, parent, tag, children: undefined }
// children to be set later by renderElementWithChildren,
// but before the init hook
{ Ctor, propsData, listeners, parent, tag, children }
)
return vnode
}

61
src/core/vdom/create-element.js

@ -7,47 +7,12 @@ import { normalizeChildren } from './helpers'
import { renderState } from '../instance/render'
import { warn, resolveAsset } from '../util/index'
export function renderElementWithChildren (
vnode: VNode | void,
children: VNodeChildren | void
): VNode | Array<VNode> | void {
if (vnode) {
const componentOptions = vnode.componentOptions
if (componentOptions) {
if (process.env.NODE_ENV !== 'production' &&
children && typeof children !== 'function') {
warn(
'A component\'s children should be a function that returns the ' +
'children array. This allows the component to track the children ' +
'dependencies and optimizes re-rendering.'
)
}
const CtorOptions = componentOptions.Ctor.options
// functional component
if (CtorOptions.functional) {
return CtorOptions.render.call(
null,
componentOptions.parent.$createElement, // h
componentOptions.propsData || {}, // props
normalizeChildren(children) // children
)
} else {
// normal component
componentOptions.children = children
}
} else {
// normal element
vnode.setChildren(normalizeChildren(children))
}
}
return vnode
}
export function renderElement (
export function createElement (
tag?: string | Class<Component> | Function | Object,
data?: VNodeData,
children?: VNodeChildren | void,
namespace?: string
): VNode | void {
): VNode | Array<VNode> | void {
// make sure to expose real self instead of proxy
const context: Component = this._self
const parent: ?Component = renderState.activeInstance
@ -67,12 +32,12 @@ export function renderElement (
let Ctor
if (config.isReservedTag(tag)) {
return new VNode(
tag, data,
undefined, undefined, undefined,
tag, data, normalizeChildren(children),
undefined, undefined,
namespace, context, host
)
} else if ((Ctor = resolveAsset(context.$options, 'components', tag))) {
return createComponent(Ctor, data, parent, context, host, tag)
return createComponent(Ctor, data, parent, context, host, children, tag)
} else {
if (process.env.NODE_ENV !== 'production') {
if (
@ -88,20 +53,12 @@ export function renderElement (
}
}
return new VNode(
tag, data,
undefined, undefined, undefined,
tag, data, normalizeChildren(children),
undefined, undefined,
namespace, context, host
)
}
} else {
return createComponent(tag, data, parent, context, host)
return createComponent(tag, data, parent, context, host, children)
}
}
export function renderStatic (index?: number): Object | void {
return this._staticTrees[index] || (
this._staticTrees[index] = this.$options.staticRenderFns[index].call(
this._renderProxy
)
)
}

3
src/core/vdom/helpers.js

@ -3,7 +3,7 @@
import { isPrimitive } from '../util/index'
import VNode from './vnode'
export function normalizeChildren (children: any): Array<VNode> {
export function normalizeChildren (children: any): Array<VNode> | void {
// invoke children thunks.
// components always receive their children as thunks so that they
// can perform the actual render inside their own dependency collection cycle.
@ -38,7 +38,6 @@ export function normalizeChildren (children: any): Array<VNode> {
}
return res
}
return []
}
function createTextVNode (val) {

6
src/core/vdom/vnode.js

@ -18,7 +18,7 @@ export default class VNode {
constructor (
tag?: string,
data?: VNodeData,
children?: Array<VNode>,
children?: Array<VNode> | void,
text?: string,
elm?: Node,
ns?: string,
@ -47,10 +47,6 @@ export default class VNode {
constructHook(this)
}
}
setChildren (children?: Array<VNode>) {
this.children = children
}
}
export const emptyVNode = () => new VNode(undefined, undefined, undefined, '')

4
src/platforms/web/compiler/modules/transition.js

@ -26,9 +26,9 @@ function genData (el: ASTElement): string {
function transformCode (el: ASTElement, code: string): string {
return el.transitionMode
? `_h(_e('TransitionControl',{props:{mode:${
? `_h('TransitionControl',{props:{mode:${
el.transitionMode
},child:${code}}}))`
},child:${code}}})`
: code
}

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

@ -34,72 +34,72 @@ describe('codegen', () => {
it('generate directive', () => {
assertCodegen(
'<p v-custom1:arg1.modifire="value1" v-custom2><p>',
`with(this){return _h(_e('p',{directives:[{name:"custom1",value:(value1),expression:"value1",arg:"arg1",modifiers:{"modifire":true}},{name:"custom2",arg:"arg1"}]}))}`
`with(this){return _h('p',{directives:[{name:"custom1",value:(value1),expression:"value1",arg:"arg1",modifiers:{"modifire":true}},{name:"custom2",arg:"arg1"}]})}`
)
})
it('generate v-for directive', () => {
assertCodegen(
'<li v-for="item in items" :key="item.uid"></li>',
`with(this){return (items)&&_l((items),function(item){return _h(_e('li',{key:item.uid}))})}`
`with(this){return (items)&&_l((items),function(item){return _h('li',{key:item.uid})})}`
)
// iterator syntax
assertCodegen(
'<li v-for="(item, i) in items"></li>',
`with(this){return (items)&&_l((items),function(item,i){return _h(_e('li'))})}`
`with(this){return (items)&&_l((items),function(item,i){return _h('li')})}`
)
assertCodegen(
'<li v-for="(item, key, index) in items"></li>',
`with(this){return (items)&&_l((items),function(item,key,index){return _h(_e('li'))})}`
`with(this){return (items)&&_l((items),function(item,key,index){return _h('li')})}`
)
})
it('generate v-if directive', () => {
assertCodegen(
'<p v-if="show">hello</p>',
`with(this){return (show)?_h(_e('p'),["hello"]):void 0}`
`with(this){return (show)?_h('p',void 0,["hello"]):void 0}`
)
})
it('generate v-else directive', () => {
assertCodegen(
'<div><p v-if="show">hello</p><p v-else>world</p></div>',
`with(this){return _h(_e('div'),[(show)?_h(_e('p'),["hello"]):_h(_e('p'),["world"])])}`
`with(this){return _h('div',void 0,[(show)?_h('p',void 0,["hello"]):_h('p',void 0,["world"])])}`
)
})
it('generate ref', () => {
assertCodegen(
'<p ref="component1"></p>',
`with(this){return _h(_e('p',{ref:"component1"}))}`
`with(this){return _h('p',{ref:"component1"})}`
)
})
it('generate ref on v-for', () => {
assertCodegen(
'<ul><li v-for="item in items" ref="component1"></li></ul>',
`with(this){return _h(_e('ul'),[(items)&&_l((items),function(item){return _h(_e('li',{ref:"component1",refInFor:true}))})])}`
`with(this){return _h('ul',void 0,[(items)&&_l((items),function(item){return _h('li',{ref:"component1",refInFor:true})})])}`
)
})
it('generate v-bind directive', () => {
assertCodegen(
'<p v-bind="test"></p>',
`with(this){return _h(_e('p',{hook:{"construct":function(n1,n2){_b(n1,test)}}}))}`
`with(this){return _h('p',{hook:{"construct":function(n1,n2){_b(n1,test)}}})}`
)
})
it('generate template tag', () => {
assertCodegen(
'<template><p>{{hello}}</p></template>',
`with(this){return [_h(_e('p'),[_s(hello)])]}`
`with(this){return [_h('p',void 0,[_s(hello)])]}`
)
})
it('generate svg tag', () => {
assertCodegen(
'<svg><text>hello world</text></svg>',
`with(this){return _h(_e('svg',void 0,'svg'),[_h(_e('text',void 0,'svg'),["hello world"])])}`
`with(this){return _h('svg',void 0,[_h('text',void 0,["hello world"],'svg')],'svg')}`
)
})
@ -109,7 +109,7 @@ describe('codegen', () => {
<matrix>
</matrix>
</math>`,
`with(this){return _h(_e('math',void 0,'math'),[_h(_e('matrix',void 0,'math'))])}`
`with(this){return _h('math',void 0,[_h('matrix',void 0,'math')],'math')}`
)
})
@ -131,14 +131,14 @@ describe('codegen', () => {
assertCodegen(
'<slot><div>hi</div></slot>',
`with(this){return ($slots["default"]||[_m(0)])}`,
[`with(this){return _h(_e('div'),["hi"])}`]
[`with(this){return _h('div',void 0,["hi"])}`]
)
})
it('generate slot target', () => {
assertCodegen(
'<p slot="one">hello world</p>',
`with(this){return _h(_e('p',{slot:"one"}),["hello world"])}`
`with(this){return _h('p',{slot:"one"},["hello world"])}`
)
})
@ -147,54 +147,54 @@ describe('codegen', () => {
assertCodegen(
'<p class="class1">hello world</p>',
'with(this){return _m(0)}',
[`with(this){return _h(_e('p',{staticClass:"class1"}),["hello world"])}`]
[`with(this){return _h('p',{staticClass:"class1"},["hello world"])}`]
)
// dynamic
assertCodegen(
'<p :class="class1">hello world</p>',
`with(this){return _h(_e('p',{class:class1}),["hello world"])}`
`with(this){return _h('p',{class:class1},["hello world"])}`
)
})
it('generate style binding', () => {
assertCodegen(
'<p :style="error">hello world</p>',
`with(this){return _h(_e('p',{style:(error)}),["hello world"])}`
`with(this){return _h('p',{style:(error)},["hello world"])}`
)
})
it('generate transition', () => {
assertCodegen(
'<p transition="expand">hello world</p>',
`with(this){return _h(_e('p',{transition:"expand"}),["hello world"])}`
`with(this){return _h('p',{transition:"expand"},["hello world"])}`
)
})
it('generate dynamic transition with transition on appear', () => {
assertCodegen(
`<p :transition="{name:'expand',appear:true}">hello world</p>`,
`with(this){return _h(_e('p',{transition:{name:'expand',appear:true}}),["hello world"])}`
`with(this){return _h('p',{transition:{name:'expand',appear:true}},["hello world"])}`
)
})
it('generate v-show directive', () => {
assertCodegen(
'<p v-show="shown">hello world</p>',
`with(this){return _h(_e('p',{directives:[{name:"show",value:(shown),expression:"shown"}],show:true}),["hello world"])}`
`with(this){return _h('p',{directives:[{name:"show",value:(shown),expression:"shown"}],show:true},["hello world"])}`
)
})
it('generate props with v-bind directive', () => {
assertCodegen(
'<p :value="msg">',
`with(this){return _h(_e('p',{props:{"value":msg}}))}`
`with(this){return _h('p',{props:{"value":msg}})}`
)
})
it('generate attrs with v-bind directive', () => {
assertCodegen(
'<input :name="field1">',
`with(this){return _h(_e('input',{attrs:{"name":field1}}))}`
`with(this){return _h('input',{attrs:{"name":field1}})}`
)
})
@ -202,79 +202,79 @@ describe('codegen', () => {
assertCodegen(
'<input name="field1">',
`with(this){return _m(0)}`,
[`with(this){return _h(_e('input',{staticAttrs:{"name":"field1"}}))}`]
[`with(this){return _h('input',{staticAttrs:{"name":"field1"}})}`]
)
})
it('generate events with v-on directive', () => {
assertCodegen(
'<input @input="onInput">',
`with(this){return _h(_e('input',{on:{"input":onInput}}))}`
`with(this){return _h('input',{on:{"input":onInput}})}`
)
})
it('generate events with keycode', () => {
assertCodegen(
'<input @input.enter="onInput">',
`with(this){return _h(_e('input',{on:{"input":function($event){if($event.keyCode!==13)return;onInput($event)}}}))}`
`with(this){return _h('input',{on:{"input":function($event){if($event.keyCode!==13)return;onInput($event)}}})}`
)
// multiple keycodes (delete)
assertCodegen(
'<input @input.delete="onInput">',
`with(this){return _h(_e('input',{on:{"input":function($event){if($event.keyCode!==8&&$event.keyCode!==46)return;onInput($event)}}}))}`
`with(this){return _h('input',{on:{"input":function($event){if($event.keyCode!==8&&$event.keyCode!==46)return;onInput($event)}}})}`
)
// number keycode
assertCodegen(
'<input @input.13="onInput">',
`with(this){return _h(_e('input',{on:{"input":function($event){if($event.keyCode!==13)return;onInput($event)}}}))}`
`with(this){return _h('input',{on:{"input":function($event){if($event.keyCode!==13)return;onInput($event)}}})}`
)
// custom keycode
assertCodegen(
'<input @input.custom="onInput">',
`with(this){return _h(_e('input',{on:{"input":function($event){if($event.keyCode!==_k("custom"))return;onInput($event)}}}))}`
`with(this){return _h('input',{on:{"input":function($event){if($event.keyCode!==_k("custom"))return;onInput($event)}}})}`
)
})
it('generate events with modifiers', () => {
assertCodegen(
'<input @input.stop="onInput">',
`with(this){return _h(_e('input',{on:{"input":function($event){$event.stopPropagation();onInput($event)}}}))}`
`with(this){return _h('input',{on:{"input":function($event){$event.stopPropagation();onInput($event)}}})}`
)
assertCodegen(
'<input @input.prevent="onInput">',
`with(this){return _h(_e('input',{on:{"input":function($event){$event.preventDefault();onInput($event)}}}))}`
`with(this){return _h('input',{on:{"input":function($event){$event.preventDefault();onInput($event)}}})}`
)
assertCodegen(
'<input @input.self="onInput">',
`with(this){return _h(_e('input',{on:{"input":function($event){if($event.target !== $event.currentTarget)return;onInput($event)}}}))}`
`with(this){return _h('input',{on:{"input":function($event){if($event.target !== $event.currentTarget)return;onInput($event)}}})}`
)
})
it('generate events with multiple modifers', () => {
assertCodegen(
'<input @input.stop.prevent.self="onInput">',
`with(this){return _h(_e('input',{on:{"input":function($event){$event.stopPropagation();$event.preventDefault();if($event.target !== $event.currentTarget)return;onInput($event)}}}))}`
`with(this){return _h('input',{on:{"input":function($event){$event.stopPropagation();$event.preventDefault();if($event.target !== $event.currentTarget)return;onInput($event)}}})}`
)
})
it('generate events with capture modifier', () => {
assertCodegen(
'<input @input.capture="onInput">',
`with(this){return _h(_e('input',{on:{"!input":function($event){onInput($event)}}}))}`
`with(this){return _h('input',{on:{"!input":function($event){onInput($event)}}})}`
)
})
it('generate events with inline statement', () => {
assertCodegen(
'<input @input="curent++">',
`with(this){return _h(_e('input',{on:{"input":function($event){curent++}}}))}`
`with(this){return _h('input',{on:{"input":function($event){curent++}}})}`
)
})
it('generate unhandled events', () => {
assertCodegen(
'<input @input="curent++">',
`with(this){return _h(_e('input',{on:{"input":function(){}}}))}`,
`with(this){return _h('input',{on:{"input":function(){}}})}`,
ast => {
ast.events.input = undefined
}
@ -284,26 +284,26 @@ describe('codegen', () => {
it('generate multiple event handlers', () => {
assertCodegen(
'<input @input="curent++" @input="onInput">',
`with(this){return _h(_e('input',{on:{"input":[function($event){curent++},onInput]}}))}`
`with(this){return _h('input',{on:{"input":[function($event){curent++},onInput]}})}`
)
})
it('generate component', () => {
assertCodegen(
'<my-component name="mycomponent1" :msg="msg" @notify="onNotify"><div>hi</div></my-component>',
`with(this){return _h(_e('my-component',{attrs:{"msg":msg},staticAttrs:{"name":"mycomponent1"},on:{"notify":onNotify}}),function(){return [_m(0)]})}`,
[`with(this){return _h(_e('div'),["hi"])}`]
`with(this){return _h('my-component',{attrs:{"msg":msg},staticAttrs:{"name":"mycomponent1"},on:{"notify":onNotify}},function(){return [_m(0)]})}`,
[`with(this){return _h('div',void 0,["hi"])}`]
)
})
it('generate is attribute', () => {
assertCodegen(
'<div is="component1"></div>',
`with(this){return _h(_e("component1",{tag:"div"}))}`
`with(this){return _h("component1",{tag:"div"})}`
)
assertCodegen(
'<div :is="component1"></div>',
`with(this){return _h(_e(component1,{tag:"div"}))}`
`with(this){return _h(component1,{tag:"div"})}`
)
})
@ -311,26 +311,26 @@ describe('codegen', () => {
// have "inline-template'"
assertCodegen(
'<my-component inline-template><p>hello world</p></my-component>',
`with(this){return _h(_e('my-component',{inlineTemplate:{render:function(){with(this){return _m(0)}},staticRenderFns:[function(){with(this){return _h(_e('p'),["hello world"])}}]}}))}`
`with(this){return _h('my-component',{inlineTemplate:{render:function(){with(this){return _m(0)}},staticRenderFns:[function(){with(this){return _h('p',void 0,["hello world"])}}]}})}`
)
// "have inline-template attrs, but not having extactly one child element
assertCodegen(
'<my-component inline-template><hr><hr></my-component>',
`with(this){return _h(_e('my-component',{inlineTemplate:{render:function(){with(this){return _m(0)}},staticRenderFns:[function(){with(this){return _h(_e('hr'))}}]}}))}`
`with(this){return _h('my-component',{inlineTemplate:{render:function(){with(this){return _m(0)}},staticRenderFns:[function(){with(this){return _h('hr')}}]}})}`
)
expect('Inline-template components must have exactly one child element.').toHaveBeenWarned()
})
it('not specified ast type', () => {
const res = generate(null, baseOptions)
expect(res.render).toBe(`with(this){return _h(_e("div"))}`)
expect(res.render).toBe(`with(this){return _h("div")}`)
expect(res.staticRenderFns).toEqual([])
})
it('not specified directives option', () => {
assertCodegen(
'<p v-if="show">hello world</p>',
`with(this){return (show)?_h(_e('p'),["hello world"]):void 0}`,
`with(this){return (show)?_h('p',void 0,["hello world"]):void 0}`,
{ isReservedTag }
)
})
@ -341,7 +341,7 @@ describe('codegen', () => {
assertCodegen(
'<div><p>hello world</p></div>',
`with(this){return _m(0)}`,
[`with(this){return _h(_e('div'),function(){return [_h(_e('p'),function(){return ["hello world"]})]})}`],
[`with(this){return _h('div',void 0,function(){return [_h('p',void 0,function(){return ["hello world"]})]})}`],
{ directives }
)
})

76
test/unit/modules/vdom/create-element.spec.js

@ -1,10 +1,6 @@
import Vue from 'vue'
import { renderState } from 'core/instance/render'
import {
renderElement,
renderElementWithChildren,
renderStatic
} from 'core/vdom/create-element'
import { createElement } from 'core/vdom/create-element'
import { emptyVNode } from 'core/vdom/vnode'
import { bind } from 'shared/util'
@ -13,13 +9,13 @@ describe('create-element', () => {
renderState.activeInstance = null
})
it('render vnode with basic reserved tag using renderElement', () => {
it('render vnode with basic reserved tag using createElement', () => {
const vm = new Vue({
data: { msg: 'hello world' }
})
const _e = bind(renderElement, vm)
const _h = bind(createElement, vm)
renderState.activeInstance = vm
const vnode = _e('p', {})
const vnode = _h('p', {})
expect(vnode.tag).toBe('p')
expect(vnode.data).toEqual({})
expect(vnode.children).toBeUndefined()
@ -29,7 +25,7 @@ describe('create-element', () => {
expect(vnode.context).toEqual(vm)
})
it('render vnode with component using renderElement', () => {
it('render vnode with component using createElement', () => {
const vm = new Vue({
data: { message: 'hello world' },
components: {
@ -38,9 +34,9 @@ describe('create-element', () => {
}
}
})
const _e = bind(renderElement, vm)
const _h = bind(createElement, vm)
renderState.activeInstance = vm
const vnode = _e('my-component', { props: { msg: vm.message }})
const vnode = _h('my-component', { props: { msg: vm.message }})
expect(vnode.tag).toMatch(/vue-component-[0-9]+/)
expect(vnode.componentOptions.propsData).toEqual({ msg: vm.message })
expect(vnode.children).toBeUndefined()
@ -50,14 +46,14 @@ describe('create-element', () => {
expect(vnode.context).toEqual(vm)
})
it('render vnode with custom tag using renderElement', () => {
it('render vnode with custom tag using createElement', () => {
const vm = new Vue({
data: { msg: 'hello world' }
})
const _e = bind(renderElement, vm)
const _h = bind(createElement, vm)
const tag = 'custom-tag'
renderState.activeInstance = vm
const vnode = _e(tag, {})
const vnode = _h(tag, {})
expect(vnode.tag).toBe('custom-tag')
expect(vnode.data).toEqual({})
expect(vnode.children).toBeUndefined()
@ -69,23 +65,23 @@ describe('create-element', () => {
expect(`Unknown custom element: <${tag}> - did you`).toHaveBeenWarned()
})
it('render empty vnode with falsy tag using renderElement', () => {
it('render empty vnode with falsy tag using createElement', () => {
const vm = new Vue({
data: { msg: 'hello world' }
})
const _e = bind(renderElement, vm)
const _h = bind(createElement, vm)
renderState.activeInstance = vm
const vnode = _e(null, {})
const vnode = _h(null, {})
expect(vnode).toEqual(emptyVNode())
})
it('render vnode with not string tag using renderElement', () => {
it('render vnode with not string tag using createElement', () => {
const vm = new Vue({
data: { msg: 'hello world' }
})
const _e = bind(renderElement, vm)
const _h = bind(createElement, vm)
renderState.activeInstance = vm
const vnode = _e(Vue.extend({ // Component class
const vnode = _h(Vue.extend({ // Component class
props: ['msg']
}), { props: { msg: vm.message }})
expect(vnode.tag).toMatch(/vue-component-[0-9]+/)
@ -97,45 +93,26 @@ describe('create-element', () => {
expect(vnode.context).toEqual(vm)
})
it('warn message that createElement cannot called when using renderElement', () => {
it('warn message that createElement cannot called when using createElement', () => {
const vm = new Vue({
data: { msg: 'hello world' }
})
const _e = bind(renderElement, vm)
_e('p', {})
const _h = bind(createElement, vm)
_h('p', {})
expect('createElement cannot be called outside of component').toHaveBeenWarned()
})
it('renderStatic', done => {
const vm = new Vue({
template: '<p>hello world</p>'
}).$mount()
waitForUpdate(() => {
const _s = bind(renderStatic, vm)
const vnode = _s(0)
expect(vnode.tag).toBe('p')
expect(vnode.data).toBeUndefined()
expect(vnode.children[0].text).toBe('hello world')
expect(vnode.elm.outerHTML).toBe('<p>hello world</p>')
expect(vnode.ns).toBeUndefined()
expect(vnode.context).toEqual(vm)
}).then(done)
})
it('render vnode with renderElementWithChildren', () => {
it('render vnode with createElement with children', () => {
const vm = new Vue({})
const _e = bind(renderElement, vm)
const _h = bind(renderElementWithChildren, vm)
const _h = bind(createElement, vm)
renderState.activeInstance = vm
const parent = _e('p', {})
const children = [_e('br'), 'hello world', _e('br')]
const vnode = _h(parent, children)
const vnode = _h('p', void 0, [_h('br'), 'hello world', _h('br')])
expect(vnode.children[0].tag).toBe('br')
expect(vnode.children[1].text).toBe('hello world')
expect(vnode.children[2].tag).toBe('br')
})
it('warn message when use renderElementWithChildren for component', () => {
it('warn message when use createElementWithChildren for component', () => {
const vm = new Vue({
data: { message: 'hello world' },
components: {
@ -144,12 +121,9 @@ describe('create-element', () => {
}
}
})
const _e = bind(renderElement, vm)
const _h = bind(renderElementWithChildren, vm)
const _h = bind(createElement, vm)
renderState.activeInstance = vm
const parent = _e('my-component', { props: { msg: vm.message }})
const children = [_e('br'), 'hello world', _e('br')]
const vnode = _h(parent, children)
const vnode = _h('my-component', { props: { msg: vm.message }}, [_h('br'), 'hello world', _h('br')])
expect(vnode.componentOptions.children[0].tag).toBe('br')
expect(vnode.componentOptions.children[1]).toBe('hello world')
expect(vnode.componentOptions.children[2].tag).toBe('br')

Loading…
Cancel
Save