wip: root Vue compat

This commit is contained in:
Evan You 2018-09-19 23:19:25 -04:00
parent 1151c7f730
commit b3208a5941
4 changed files with 46 additions and 24 deletions

View File

@ -1,5 +1,6 @@
import { VNodeFlags } from './flags' import { VNodeFlags } from './flags'
import { EMPTY_OBJ } from './utils' import { EMPTY_OBJ } from './utils'
import { h } from './h'
import { VNode, createFragment } from './vdom' import { VNode, createFragment } from './vdom'
import { Component, MountedComponent, ComponentClass } from './component' import { Component, MountedComponent, ComponentClass } from './component'
import { createTextVNode, cloneVNode } from './vdom' import { createTextVNode, cloneVNode } from './vdom'
@ -153,6 +154,7 @@ export function shouldUpdateFunctionalComponent(
return shouldUpdate return shouldUpdate
} }
// compat only
export function createComponentClassFromOptions( export function createComponentClassFromOptions(
options: ComponentOptions options: ComponentOptions
): ComponentClass { ): ComponentClass {
@ -165,7 +167,13 @@ export function createComponentClassFromOptions(
for (const key in options) { for (const key in options) {
const value = options[key] const value = options[key]
if (typeof value === 'function') { if (typeof value === 'function') {
;(ObjectComponent.prototype as any)[key] = value ;(ObjectComponent.prototype as any)[key] =
key === 'render'
? // normalize render for legacy signature
function render() {
return value.call(this, h)
}
: value
} }
if (key === 'computed') { if (key === 'computed') {
const isGet = typeof value === 'function' const isGet = typeof value === 'function'

View File

@ -1174,11 +1174,11 @@ export function createRenderer(options: RendererOptions) {
isSVG: boolean, isSVG: boolean,
endNode: RenderNode | RenderFragment | null endNode: RenderNode | RenderFragment | null
): RenderNode { ): RenderNode {
const instance = createComponentInstance( // a vnode may already have an instance if this is a compat call
parentVNode, // with new Vue()
Component, const instance =
parentComponent (__COMPAT__ && (parentVNode.children as MountedComponent)) ||
) createComponentInstance(parentVNode, Component, parentComponent)
const queueUpdate = (instance.$forceUpdate = () => { const queueUpdate = (instance.$forceUpdate = () => {
queueJob(instance._updateHandle, flushHooks) queueJob(instance._updateHandle, flushHooks)

View File

@ -10,8 +10,11 @@ export const Component = InternalComponent as ComponentClass
// observer api // observer api
export * from '@vue/observer' export * from '@vue/observer'
// internal api
export { createComponentInstance } from './componentUtils'
// flags & types // flags & types
export { FunctionalComponent } from './component' export { ComponentClass, FunctionalComponent } from './component'
export { ComponentOptions, PropType } from './componentOptions' export { ComponentOptions, PropType } from './componentOptions'
export { VNodeFlags, ChildrenFlags } from './flags' export { VNodeFlags, ChildrenFlags } from './flags'
export { VNode, VNodeData, VNodeChildren, Key, Ref, Slots, Slot } from './vdom' export { VNode, VNodeData, VNodeChildren, Key, Ref, Slots, Slot } from './vdom'

View File

@ -1,25 +1,36 @@
import { h, render, ComponentOptions } from '@vue/renderer-dom' import {
h,
render,
Component,
ComponentOptions,
createComponentInstance
} from '@vue/renderer-dom'
function Vue(options: ComponentOptions & { el: any }) { class Vue extends Component {
const { el, render: r } = options static h = h
static render = render
if (r) { constructor(options: ComponentOptions & { el: any }) {
options.render = function(props, slots) { super()
return r.call(this, h, props, slots) if (!options) {
} return
} }
const vnode = h(options)
const instance = createComponentInstance(vnode, options._normalized, null)
vnode.children = instance
function mount(el: any) { function mount(el: any) {
const dom = document.querySelector(el) const dom = document.querySelector(el)
render(h(options), dom) render(vnode, dom)
return (dom as any).vnode.children.$proxy return instance.$proxy
} }
if (el) { if (options.el) {
return mount(el) return mount(options.el)
} else { } else {
return { ;(instance as any).$mount = mount
$mount: mount return instance.$proxy
} }
} }
} }