types: use stricter HostNode typings
This commit is contained in:
parent
360f3b4f37
commit
3904678306
@ -9,8 +9,7 @@ For full exposed APIs, see `src/index.ts`. You can also run `yarn build runtime-
|
|||||||
``` ts
|
``` ts
|
||||||
import { createRenderer, createAppAPI } from '@vue/runtime-core'
|
import { createRenderer, createAppAPI } from '@vue/runtime-core'
|
||||||
|
|
||||||
// low-level render method
|
const { render, createApp } = createRenderer({
|
||||||
export const render = createRenderer({
|
|
||||||
pathcProp,
|
pathcProp,
|
||||||
insert,
|
insert,
|
||||||
remove,
|
remove,
|
||||||
@ -18,7 +17,10 @@ export const render = createRenderer({
|
|||||||
// ...
|
// ...
|
||||||
})
|
})
|
||||||
|
|
||||||
export const createApp = createAppAPI(render)
|
// `render` is the low-level API
|
||||||
|
// `createApp` returns an app instance with configurable context shared
|
||||||
|
// by the entire app tree.
|
||||||
|
export { render, createApp }
|
||||||
|
|
||||||
export * from '@vue/runtime-core'
|
export * from '@vue/runtime-core'
|
||||||
```
|
```
|
||||||
|
@ -2,13 +2,13 @@ import { Component, Data, ComponentInternalInstance } from './component'
|
|||||||
import { ComponentOptions } from './componentOptions'
|
import { ComponentOptions } from './componentOptions'
|
||||||
import { ComponentPublicInstance } from './componentPublicInstanceProxy'
|
import { ComponentPublicInstance } from './componentPublicInstanceProxy'
|
||||||
import { Directive } from './directives'
|
import { Directive } from './directives'
|
||||||
import { HostNode, RootRenderFunction } from './createRenderer'
|
import { RootRenderFunction } from './createRenderer'
|
||||||
import { InjectionKey } from './apiInject'
|
import { InjectionKey } from './apiInject'
|
||||||
import { isFunction } from '@vue/shared'
|
import { isFunction } from '@vue/shared'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
import { createVNode } from './vnode'
|
import { createVNode } from './vnode'
|
||||||
|
|
||||||
export interface App {
|
export interface App<HostElement = any> {
|
||||||
config: AppConfig
|
config: AppConfig
|
||||||
use(plugin: Plugin, options?: any): this
|
use(plugin: Plugin, options?: any): this
|
||||||
mixin(mixin: ComponentOptions): this
|
mixin(mixin: ComponentOptions): this
|
||||||
@ -18,7 +18,7 @@ export interface App {
|
|||||||
directive(name: string, directive: Directive): this
|
directive(name: string, directive: Directive): this
|
||||||
mount(
|
mount(
|
||||||
rootComponent: Component,
|
rootComponent: Component,
|
||||||
rootContainer: string | HostNode,
|
rootContainer: HostElement,
|
||||||
rootProps?: Data
|
rootProps?: Data
|
||||||
): ComponentPublicInstance
|
): ComponentPublicInstance
|
||||||
provide<T>(key: InjectionKey<T> | string, value: T): void
|
provide<T>(key: InjectionKey<T> | string, value: T): void
|
||||||
@ -70,7 +70,9 @@ export function createAppContext(): AppContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createAppAPI(render: RootRenderFunction): () => App {
|
export function createAppAPI<HostNode, HostElement>(
|
||||||
|
render: RootRenderFunction<HostNode, HostElement>
|
||||||
|
): () => App<HostElement> {
|
||||||
return function createApp(): App {
|
return function createApp(): App {
|
||||||
const context = createAppContext()
|
const context = createAppContext()
|
||||||
|
|
||||||
@ -128,7 +130,11 @@ export function createAppAPI(render: RootRenderFunction): () => App {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mount(rootComponent, rootContainer, rootProps?: Data): any {
|
mount(
|
||||||
|
rootComponent: Component,
|
||||||
|
rootContainer: string | HostElement,
|
||||||
|
rootProps?: Data
|
||||||
|
): any {
|
||||||
if (!isMounted) {
|
if (!isMounted) {
|
||||||
const vnode = createVNode(rootComponent, rootProps)
|
const vnode = createVNode(rootComponent, rootProps)
|
||||||
// store app context on the root VNode.
|
// store app context on the root VNode.
|
||||||
|
@ -38,6 +38,8 @@ import { PatchFlags } from './patchFlags'
|
|||||||
import { ShapeFlags } from './shapeFlags'
|
import { ShapeFlags } from './shapeFlags'
|
||||||
import { pushWarningContext, popWarningContext, warn } from './warning'
|
import { pushWarningContext, popWarningContext, warn } from './warning'
|
||||||
import { invokeDirectiveHook } from './directives'
|
import { invokeDirectiveHook } from './directives'
|
||||||
|
import { ComponentPublicInstance } from './componentPublicInstanceProxy'
|
||||||
|
import { App, createAppAPI } from './apiApp'
|
||||||
|
|
||||||
const prodEffectOptions = {
|
const prodEffectOptions = {
|
||||||
scheduler: queueJob
|
scheduler: queueJob
|
||||||
@ -67,40 +69,64 @@ function invokeHooks(hooks: Function[], arg?: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type HostNode = any
|
export interface RendererOptions<HostNode = any, HostElement = any> {
|
||||||
|
|
||||||
export interface RendererOptions {
|
|
||||||
patchProp(
|
patchProp(
|
||||||
el: HostNode,
|
el: HostElement,
|
||||||
key: string,
|
key: string,
|
||||||
value: any,
|
value: any,
|
||||||
oldValue: any,
|
oldValue: any,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
prevChildren?: VNode[],
|
prevChildren?: VNode<HostNode, HostElement>[],
|
||||||
parentComponent?: ComponentInternalInstance | null,
|
parentComponent?: ComponentInternalInstance | null,
|
||||||
unmountChildren?: (
|
unmountChildren?: (
|
||||||
children: VNode[],
|
children: VNode<HostNode, HostElement>[],
|
||||||
parentComponent: ComponentInternalInstance | null
|
parentComponent: ComponentInternalInstance | null
|
||||||
) => void
|
) => void
|
||||||
): void
|
): void
|
||||||
insert(el: HostNode, parent: HostNode, anchor?: HostNode): void
|
insert(el: HostNode, parent: HostElement, anchor?: HostNode | null): void
|
||||||
remove(el: HostNode): void
|
remove(el: HostNode): void
|
||||||
createElement(type: string, isSVG?: boolean): HostNode
|
createElement(type: string, isSVG?: boolean): HostElement
|
||||||
createText(text: string): HostNode
|
createText(text: string): HostNode
|
||||||
createComment(text: string): HostNode
|
createComment(text: string): HostNode
|
||||||
setText(node: HostNode, text: string): void
|
setText(node: HostNode, text: string): void
|
||||||
setElementText(node: HostNode, text: string): void
|
setElementText(node: HostElement, text: string): void
|
||||||
parentNode(node: HostNode): HostNode | null
|
parentNode(node: HostNode): HostNode | null
|
||||||
nextSibling(node: HostNode): HostNode | null
|
nextSibling(node: HostNode): HostNode | null
|
||||||
querySelector(selector: string): HostNode | null
|
querySelector(selector: string): HostElement | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RootRenderFunction = (
|
export type RootRenderFunction<HostNode, HostElement> = (
|
||||||
vnode: VNode | null,
|
vnode: VNode<HostNode, HostElement> | null,
|
||||||
dom: HostNode | string
|
dom: HostElement | string
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
export function createRenderer(options: RendererOptions): RootRenderFunction {
|
/**
|
||||||
|
* The createRenderer function accepts two generic arguments:
|
||||||
|
* HostNode and HostElement, corresponding to Node and Element types in the
|
||||||
|
* host environment. For example, for runtime-dom, HostNode would be the DOM
|
||||||
|
* `Node` interface and HostElement would be the DOM `Element` interface.
|
||||||
|
*
|
||||||
|
* Custom renderers can pass in the platform specific types like this:
|
||||||
|
*
|
||||||
|
* ``` js
|
||||||
|
* const { render, createApp } = createRenderer<Node, Element>({
|
||||||
|
* patchProp,
|
||||||
|
* ...nodeOps
|
||||||
|
* })
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function createRenderer<
|
||||||
|
HostNode extends object = any,
|
||||||
|
HostElement extends HostNode = any
|
||||||
|
>(
|
||||||
|
options: RendererOptions<HostNode, HostElement>
|
||||||
|
): {
|
||||||
|
render: RootRenderFunction<HostNode, HostElement>
|
||||||
|
createApp: () => App<HostElement>
|
||||||
|
} {
|
||||||
|
type HostVNode = VNode<HostNode, HostElement>
|
||||||
|
type HostVNodeChildren = VNodeChildren<HostNode, HostElement>
|
||||||
|
|
||||||
const {
|
const {
|
||||||
insert: hostInsert,
|
insert: hostInsert,
|
||||||
remove: hostRemove,
|
remove: hostRemove,
|
||||||
@ -116,10 +142,10 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
} = options
|
} = options
|
||||||
|
|
||||||
function patch(
|
function patch(
|
||||||
n1: VNode | null, // null means this is a mount
|
n1: HostVNode | null, // null means this is a mount
|
||||||
n2: VNode,
|
n2: HostVNode,
|
||||||
container: HostNode,
|
container: HostElement,
|
||||||
anchor: HostNode = null,
|
anchor: HostNode | null = null,
|
||||||
parentComponent: ComponentInternalInstance | null = null,
|
parentComponent: ComponentInternalInstance | null = null,
|
||||||
isSVG: boolean = false,
|
isSVG: boolean = false,
|
||||||
optimized: boolean = false
|
optimized: boolean = false
|
||||||
@ -183,16 +209,16 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
optimized
|
optimized
|
||||||
)
|
)
|
||||||
} else if (__DEV__) {
|
} else if (__DEV__) {
|
||||||
warn('Invalid VNode type:', n2.type, `(${typeof n2.type})`)
|
warn('Invalid HostVNode type:', n2.type, `(${typeof n2.type})`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function processText(
|
function processText(
|
||||||
n1: VNode | null,
|
n1: HostVNode | null,
|
||||||
n2: VNode,
|
n2: HostVNode,
|
||||||
container: HostNode,
|
container: HostElement,
|
||||||
anchor: HostNode
|
anchor: HostNode | null
|
||||||
) {
|
) {
|
||||||
if (n1 == null) {
|
if (n1 == null) {
|
||||||
hostInsert(
|
hostInsert(
|
||||||
@ -201,7 +227,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
anchor
|
anchor
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
const el = (n2.el = n1.el)
|
const el = (n2.el = n1.el) as HostNode
|
||||||
if (n2.children !== n1.children) {
|
if (n2.children !== n1.children) {
|
||||||
hostSetText(el, n2.children as string)
|
hostSetText(el, n2.children as string)
|
||||||
}
|
}
|
||||||
@ -209,10 +235,10 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function processEmptyNode(
|
function processEmptyNode(
|
||||||
n1: VNode | null,
|
n1: HostVNode | null,
|
||||||
n2: VNode,
|
n2: HostVNode,
|
||||||
container: HostNode,
|
container: HostElement,
|
||||||
anchor: HostNode
|
anchor: HostNode | null
|
||||||
) {
|
) {
|
||||||
if (n1 == null) {
|
if (n1 == null) {
|
||||||
hostInsert((n2.el = hostCreateComment('')), container, anchor)
|
hostInsert((n2.el = hostCreateComment('')), container, anchor)
|
||||||
@ -222,10 +248,10 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function processElement(
|
function processElement(
|
||||||
n1: VNode | null,
|
n1: HostVNode | null,
|
||||||
n2: VNode,
|
n2: HostVNode,
|
||||||
container: HostNode,
|
container: HostElement,
|
||||||
anchor: HostNode,
|
anchor: HostNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
@ -241,9 +267,9 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mountElement(
|
function mountElement(
|
||||||
vnode: VNode,
|
vnode: HostVNode,
|
||||||
container: HostNode,
|
container: HostElement,
|
||||||
anchor: HostNode,
|
anchor: HostNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
) {
|
) {
|
||||||
@ -264,7 +290,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
hostSetElementText(el, vnode.children as string)
|
hostSetElementText(el, vnode.children as string)
|
||||||
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
mountChildren(
|
mountChildren(
|
||||||
vnode.children as VNodeChildren,
|
vnode.children as HostVNodeChildren,
|
||||||
el,
|
el,
|
||||||
null,
|
null,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -280,9 +306,9 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mountChildren(
|
function mountChildren(
|
||||||
children: VNodeChildren,
|
children: HostVNodeChildren,
|
||||||
container: HostNode,
|
container: HostElement,
|
||||||
anchor: HostNode,
|
anchor: HostNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
start: number = 0
|
start: number = 0
|
||||||
@ -294,13 +320,13 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function patchElement(
|
function patchElement(
|
||||||
n1: VNode,
|
n1: HostVNode,
|
||||||
n2: VNode,
|
n2: HostVNode,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) {
|
) {
|
||||||
const el = (n2.el = n1.el)
|
const el = (n2.el = n1.el) as HostElement
|
||||||
const { patchFlag, dynamicChildren } = n2
|
const { patchFlag, dynamicChildren } = n2
|
||||||
const oldProps = (n1 && n1.props) || EMPTY_OBJ
|
const oldProps = (n1 && n1.props) || EMPTY_OBJ
|
||||||
const newProps = n2.props || EMPTY_OBJ
|
const newProps = n2.props || EMPTY_OBJ
|
||||||
@ -353,7 +379,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
next,
|
next,
|
||||||
prev,
|
prev,
|
||||||
isSVG,
|
isSVG,
|
||||||
n1.children as VNode[],
|
n1.children as HostVNode[],
|
||||||
parentComponent,
|
parentComponent,
|
||||||
unmountChildren
|
unmountChildren
|
||||||
)
|
)
|
||||||
@ -378,7 +404,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
|
|
||||||
if (dynamicChildren != null) {
|
if (dynamicChildren != null) {
|
||||||
// children fast path
|
// children fast path
|
||||||
const olddynamicChildren = n1.dynamicChildren as VNode[]
|
const olddynamicChildren = n1.dynamicChildren as HostVNode[]
|
||||||
for (let i = 0; i < dynamicChildren.length; i++) {
|
for (let i = 0; i < dynamicChildren.length; i++) {
|
||||||
patch(
|
patch(
|
||||||
olddynamicChildren[i],
|
olddynamicChildren[i],
|
||||||
@ -403,8 +429,8 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function patchProps(
|
function patchProps(
|
||||||
el: HostNode,
|
el: HostElement,
|
||||||
vnode: VNode,
|
vnode: HostVNode,
|
||||||
oldProps: any,
|
oldProps: any,
|
||||||
newProps: any,
|
newProps: any,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
@ -422,7 +448,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
next,
|
next,
|
||||||
prev,
|
prev,
|
||||||
isSVG,
|
isSVG,
|
||||||
vnode.children as VNode[],
|
vnode.children as HostVNode[],
|
||||||
parentComponent,
|
parentComponent,
|
||||||
unmountChildren
|
unmountChildren
|
||||||
)
|
)
|
||||||
@ -438,7 +464,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
isSVG,
|
isSVG,
|
||||||
vnode.children as VNode[],
|
vnode.children as HostVNode[],
|
||||||
parentComponent,
|
parentComponent,
|
||||||
unmountChildren
|
unmountChildren
|
||||||
)
|
)
|
||||||
@ -449,24 +475,26 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function processFragment(
|
function processFragment(
|
||||||
n1: VNode | null,
|
n1: HostVNode | null,
|
||||||
n2: VNode,
|
n2: HostVNode,
|
||||||
container: HostNode,
|
container: HostElement,
|
||||||
anchor: HostNode,
|
anchor: HostNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) {
|
) {
|
||||||
const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateComment(''))
|
const fragmentStartAnchor = (n2.el = n1
|
||||||
|
? n1.el
|
||||||
|
: hostCreateComment('')) as HostNode
|
||||||
const fragmentEndAnchor = (n2.anchor = n1
|
const fragmentEndAnchor = (n2.anchor = n1
|
||||||
? n1.anchor
|
? n1.anchor
|
||||||
: hostCreateComment(''))
|
: hostCreateComment('')) as HostNode
|
||||||
if (n1 == null) {
|
if (n1 == null) {
|
||||||
hostInsert(fragmentStartAnchor, container, anchor)
|
hostInsert(fragmentStartAnchor, container, anchor)
|
||||||
hostInsert(fragmentEndAnchor, container, anchor)
|
hostInsert(fragmentEndAnchor, container, anchor)
|
||||||
// a fragment can only have array children
|
// a fragment can only have array children
|
||||||
mountChildren(
|
mountChildren(
|
||||||
n2.children as VNodeChildren,
|
n2.children as HostVNodeChildren,
|
||||||
container,
|
container,
|
||||||
fragmentEndAnchor,
|
fragmentEndAnchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -486,10 +514,10 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function processPortal(
|
function processPortal(
|
||||||
n1: VNode | null,
|
n1: HostVNode | null,
|
||||||
n2: VNode,
|
n2: HostVNode,
|
||||||
container: HostNode,
|
container: HostElement,
|
||||||
anchor: HostNode,
|
anchor: HostNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
@ -505,7 +533,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
hostSetElementText(target, children as string)
|
hostSetElementText(target, children as string)
|
||||||
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
mountChildren(
|
mountChildren(
|
||||||
children as VNodeChildren,
|
children as HostVNodeChildren,
|
||||||
target,
|
target,
|
||||||
null,
|
null,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -517,7 +545,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// update content
|
// update content
|
||||||
const target = (n2.target = n1.target)
|
const target = (n2.target = n1.target) as HostElement
|
||||||
if (patchFlag === PatchFlags.TEXT) {
|
if (patchFlag === PatchFlags.TEXT) {
|
||||||
hostSetElementText(target, children as string)
|
hostSetElementText(target, children as string)
|
||||||
} else if (!optimized) {
|
} else if (!optimized) {
|
||||||
@ -534,8 +562,8 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
hostSetElementText(target, '')
|
hostSetElementText(target, '')
|
||||||
hostSetElementText(nextTarget, children as string)
|
hostSetElementText(nextTarget, children as string)
|
||||||
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
for (let i = 0; i < (children as VNode[]).length; i++) {
|
for (let i = 0; i < (children as HostVNode[]).length; i++) {
|
||||||
move((children as VNode[])[i], nextTarget, null)
|
move((children as HostVNode[])[i], nextTarget, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (__DEV__) {
|
} else if (__DEV__) {
|
||||||
@ -548,10 +576,10 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function processComponent(
|
function processComponent(
|
||||||
n1: VNode | null,
|
n1: HostVNode | null,
|
||||||
n2: VNode,
|
n2: HostVNode,
|
||||||
container: HostNode,
|
container: HostElement,
|
||||||
anchor: HostNode,
|
anchor: HostNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
@ -580,9 +608,9 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mountComponent(
|
function mountComponent(
|
||||||
initialVNode: VNode,
|
initialVNode: HostVNode,
|
||||||
container: HostNode,
|
container: HostElement,
|
||||||
anchor: HostNode,
|
anchor: HostNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
) {
|
) {
|
||||||
@ -624,7 +652,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
} else {
|
} else {
|
||||||
// updateComponent
|
// updateComponent
|
||||||
// This is triggered by mutation of component's own state (next: null)
|
// This is triggered by mutation of component's own state (next: null)
|
||||||
// OR parent calling processComponent (next: VNode)
|
// OR parent calling processComponent (next: HostVNode)
|
||||||
const { next } = instance
|
const { next } = instance
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
@ -654,7 +682,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
prevTree,
|
prevTree,
|
||||||
nextTree,
|
nextTree,
|
||||||
// parent may have changed if it's in a portal
|
// parent may have changed if it's in a portal
|
||||||
hostParentNode(prevTree.el),
|
hostParentNode(prevTree.el as HostNode) as HostElement,
|
||||||
// anchor may have changed if it's in a fragment
|
// anchor may have changed if it's in a fragment
|
||||||
getNextHostNode(prevTree),
|
getNextHostNode(prevTree),
|
||||||
instance,
|
instance,
|
||||||
@ -689,10 +717,10 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function patchChildren(
|
function patchChildren(
|
||||||
n1: VNode | null,
|
n1: HostVNode | null,
|
||||||
n2: VNode,
|
n2: HostVNode,
|
||||||
container: HostNode,
|
container: HostElement,
|
||||||
anchor: HostNode,
|
anchor: HostNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean = false
|
optimized: boolean = false
|
||||||
@ -708,8 +736,8 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
// this could be either fully-keyed or mixed (some keyed some not)
|
// this could be either fully-keyed or mixed (some keyed some not)
|
||||||
// presence of patchFlag means children are guaranteed to be arrays
|
// presence of patchFlag means children are guaranteed to be arrays
|
||||||
patchKeyedChildren(
|
patchKeyedChildren(
|
||||||
c1 as VNode[],
|
c1 as HostVNode[],
|
||||||
c2 as VNodeChildren,
|
c2 as HostVNodeChildren,
|
||||||
container,
|
container,
|
||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -720,8 +748,8 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
} else if (patchFlag & PatchFlags.UNKEYED) {
|
} else if (patchFlag & PatchFlags.UNKEYED) {
|
||||||
// unkeyed
|
// unkeyed
|
||||||
patchUnkeyedChildren(
|
patchUnkeyedChildren(
|
||||||
c1 as VNode[],
|
c1 as HostVNode[],
|
||||||
c2 as VNodeChildren,
|
c2 as HostVNodeChildren,
|
||||||
container,
|
container,
|
||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -735,7 +763,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
|
if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
|
||||||
// text children fast path
|
// text children fast path
|
||||||
if (prevShapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
if (prevShapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
unmountChildren(c1 as VNode[], parentComponent)
|
unmountChildren(c1 as HostVNode[], parentComponent)
|
||||||
}
|
}
|
||||||
if (c2 !== c1) {
|
if (c2 !== c1) {
|
||||||
hostSetElementText(container, c2 as string)
|
hostSetElementText(container, c2 as string)
|
||||||
@ -745,7 +773,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
hostSetElementText(container, '')
|
hostSetElementText(container, '')
|
||||||
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
mountChildren(
|
mountChildren(
|
||||||
c2 as VNodeChildren,
|
c2 as HostVNodeChildren,
|
||||||
container,
|
container,
|
||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -756,8 +784,8 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
// two arrays, cannot assume anything, do full diff
|
// two arrays, cannot assume anything, do full diff
|
||||||
patchKeyedChildren(
|
patchKeyedChildren(
|
||||||
c1 as VNode[],
|
c1 as HostVNode[],
|
||||||
c2 as VNodeChildren,
|
c2 as HostVNodeChildren,
|
||||||
container,
|
container,
|
||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -766,17 +794,17 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// c2 is null in this case
|
// c2 is null in this case
|
||||||
unmountChildren(c1 as VNode[], parentComponent, true)
|
unmountChildren(c1 as HostVNode[], parentComponent, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function patchUnkeyedChildren(
|
function patchUnkeyedChildren(
|
||||||
c1: VNode[],
|
c1: HostVNode[],
|
||||||
c2: VNodeChildren,
|
c2: HostVNodeChildren,
|
||||||
container: HostNode,
|
container: HostElement,
|
||||||
anchor: HostNode,
|
anchor: HostNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
@ -810,10 +838,10 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
|
|
||||||
// can be all-keyed or mixed
|
// can be all-keyed or mixed
|
||||||
function patchKeyedChildren(
|
function patchKeyedChildren(
|
||||||
c1: VNode[],
|
c1: HostVNode[],
|
||||||
c2: VNodeChildren,
|
c2: HostVNodeChildren,
|
||||||
container: HostNode,
|
container: HostElement,
|
||||||
parentAnchor: HostNode,
|
parentAnchor: HostNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
@ -878,7 +906,8 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
if (i > e1) {
|
if (i > e1) {
|
||||||
if (i <= e2) {
|
if (i <= e2) {
|
||||||
const nextPos = e2 + 1
|
const nextPos = e2 + 1
|
||||||
const anchor = nextPos < l2 ? (c2[nextPos] as VNode).el : parentAnchor
|
const anchor =
|
||||||
|
nextPos < l2 ? (c2[nextPos] as HostVNode).el : parentAnchor
|
||||||
while (i <= e2) {
|
while (i <= e2) {
|
||||||
patch(
|
patch(
|
||||||
null,
|
null,
|
||||||
@ -960,7 +989,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
} else {
|
} else {
|
||||||
// key-less node, try to locate a key-less node of the same type
|
// key-less node, try to locate a key-less node of the same type
|
||||||
for (j = s2; j <= e2; j++) {
|
for (j = s2; j <= e2; j++) {
|
||||||
if (isSameType(prevChild, c2[j] as VNode)) {
|
if (isSameType(prevChild, c2[j] as HostVNode)) {
|
||||||
newIndex = j
|
newIndex = j
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -977,7 +1006,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
patch(
|
patch(
|
||||||
prevChild,
|
prevChild,
|
||||||
c2[newIndex] as VNode,
|
c2[newIndex] as HostVNode,
|
||||||
container,
|
container,
|
||||||
null,
|
null,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -997,9 +1026,11 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
// looping backwards so that we can use last patched node as anchor
|
// looping backwards so that we can use last patched node as anchor
|
||||||
for (i = toBePatched - 1; i >= 0; i--) {
|
for (i = toBePatched - 1; i >= 0; i--) {
|
||||||
const nextIndex = s2 + i
|
const nextIndex = s2 + i
|
||||||
const nextChild = c2[nextIndex] as VNode
|
const nextChild = c2[nextIndex] as HostVNode
|
||||||
const anchor =
|
const anchor =
|
||||||
nextIndex + 1 < l2 ? (c2[nextIndex + 1] as VNode).el : parentAnchor
|
nextIndex + 1 < l2
|
||||||
|
? (c2[nextIndex + 1] as HostVNode).el
|
||||||
|
: parentAnchor
|
||||||
if (newIndexToOldIndexMap[i] === 0) {
|
if (newIndexToOldIndexMap[i] === 0) {
|
||||||
// mount new
|
// mount new
|
||||||
patch(null, nextChild, container, anchor, parentComponent, isSVG)
|
patch(null, nextChild, container, anchor, parentComponent, isSVG)
|
||||||
@ -1017,25 +1048,29 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function move(vnode: VNode, container: HostNode, anchor: HostNode) {
|
function move(
|
||||||
|
vnode: HostVNode,
|
||||||
|
container: HostElement,
|
||||||
|
anchor: HostNode | null
|
||||||
|
) {
|
||||||
if (vnode.component !== null) {
|
if (vnode.component !== null) {
|
||||||
move(vnode.component.subTree, container, anchor)
|
move(vnode.component.subTree, container, anchor)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (vnode.type === Fragment) {
|
if (vnode.type === Fragment) {
|
||||||
hostInsert(vnode.el, container, anchor)
|
hostInsert(vnode.el as HostNode, container, anchor)
|
||||||
const children = vnode.children as VNode[]
|
const children = vnode.children as HostVNode[]
|
||||||
for (let i = 0; i < children.length; i++) {
|
for (let i = 0; i < children.length; i++) {
|
||||||
hostInsert(children[i].el, container, anchor)
|
hostInsert(children[i].el as HostNode, container, anchor)
|
||||||
}
|
}
|
||||||
hostInsert(vnode.anchor, container, anchor)
|
hostInsert(vnode.anchor as HostNode, container, anchor)
|
||||||
} else {
|
} else {
|
||||||
hostInsert(vnode.el, container, anchor)
|
hostInsert(vnode.el as HostNode, container, anchor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function unmount(
|
function unmount(
|
||||||
vnode: VNode,
|
vnode: HostVNode,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
doRemove?: boolean
|
doRemove?: boolean
|
||||||
) {
|
) {
|
||||||
@ -1069,14 +1104,14 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
unmountChildren(dynamicChildren, parentComponent, shouldRemoveChildren)
|
unmountChildren(dynamicChildren, parentComponent, shouldRemoveChildren)
|
||||||
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
unmountChildren(
|
unmountChildren(
|
||||||
children as VNode[],
|
children as HostVNode[],
|
||||||
parentComponent,
|
parentComponent,
|
||||||
shouldRemoveChildren
|
shouldRemoveChildren
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doRemove) {
|
if (doRemove) {
|
||||||
hostRemove(vnode.el)
|
hostRemove(vnode.el as HostNode)
|
||||||
if (anchor != null) hostRemove(anchor)
|
if (anchor != null) hostRemove(anchor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1110,7 +1145,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function unmountChildren(
|
function unmountChildren(
|
||||||
children: VNode[],
|
children: HostVNode[],
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
doRemove?: boolean,
|
doRemove?: boolean,
|
||||||
start: number = 0
|
start: number = 0
|
||||||
@ -1120,9 +1155,9 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNextHostNode(vnode: VNode): HostNode {
|
function getNextHostNode(vnode: HostVNode): HostNode | null {
|
||||||
return vnode.component === null
|
return vnode.component === null
|
||||||
? hostNextSibling(vnode.anchor || vnode.el)
|
? hostNextSibling((vnode.anchor || vnode.el) as HostNode)
|
||||||
: getNextHostNode(vnode.component.subTree)
|
: getNextHostNode(vnode.component.subTree)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1130,7 +1165,7 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
ref: string | Function | Ref<any>,
|
ref: string | Function | Ref<any>,
|
||||||
oldRef: string | Function | Ref<any> | null,
|
oldRef: string | Function | Ref<any> | null,
|
||||||
parent: ComponentInternalInstance,
|
parent: ComponentInternalInstance,
|
||||||
value: HostNode | ComponentInternalInstance | null
|
value: HostNode | ComponentPublicInstance | null
|
||||||
) {
|
) {
|
||||||
const refs = parent.refs === EMPTY_OBJ ? (parent.refs = {}) : parent.refs
|
const refs = parent.refs === EMPTY_OBJ ? (parent.refs = {}) : parent.refs
|
||||||
const renderContext = toRaw(parent.renderContext)
|
const renderContext = toRaw(parent.renderContext)
|
||||||
@ -1163,39 +1198,33 @@ export function createRenderer(options: RendererOptions): RootRenderFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return function render(vnode: VNode | null, dom: HostNode | string) {
|
function render(vnode: HostVNode | null, rawContainer: HostElement | string) {
|
||||||
if (isString(dom)) {
|
let container: any = rawContainer
|
||||||
if (isFunction(hostQuerySelector)) {
|
if (isString(container)) {
|
||||||
dom = hostQuerySelector(dom)
|
container = hostQuerySelector(container)
|
||||||
if (!dom) {
|
if (!container) {
|
||||||
if (__DEV__) {
|
|
||||||
warn(
|
|
||||||
`Failed to locate root container: ` +
|
|
||||||
`querySelector returned null.`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
warn(
|
warn(
|
||||||
`Failed to locate root container: ` +
|
`Failed to locate root container: ` + `querySelector returned null.`
|
||||||
`target platform does not support querySelector.`
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (vnode == null) {
|
if (vnode == null) {
|
||||||
debugger
|
if (container._vnode) {
|
||||||
if (dom._vnode) {
|
unmount(container._vnode, null, true)
|
||||||
unmount(dom._vnode, null, true)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
patch(dom._vnode, vnode, dom)
|
patch(container._vnode || null, vnode, container)
|
||||||
}
|
}
|
||||||
flushPostFlushCbs()
|
flushPostFlushCbs()
|
||||||
dom._vnode = vnode
|
container._vnode = vnode
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
render,
|
||||||
|
createApp: createAppAPI(render)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ import { warn } from './warning'
|
|||||||
import { ComponentInternalInstance } from './component'
|
import { ComponentInternalInstance } from './component'
|
||||||
import { currentRenderingInstance } from './componentRenderUtils'
|
import { currentRenderingInstance } from './componentRenderUtils'
|
||||||
import { callWithAsyncErrorHandling, ErrorCodes } from './errorHandling'
|
import { callWithAsyncErrorHandling, ErrorCodes } from './errorHandling'
|
||||||
import { HostNode } from './createRenderer'
|
|
||||||
import { ComponentPublicInstance } from './componentPublicInstanceProxy'
|
import { ComponentPublicInstance } from './componentPublicInstanceProxy'
|
||||||
|
|
||||||
export interface DirectiveBinding {
|
export interface DirectiveBinding {
|
||||||
@ -29,7 +28,7 @@ export interface DirectiveBinding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type DirectiveHook = (
|
export type DirectiveHook = (
|
||||||
el: HostNode,
|
el: any,
|
||||||
binding: DirectiveBinding,
|
binding: DirectiveBinding,
|
||||||
vnode: VNode,
|
vnode: VNode,
|
||||||
prevVNode: VNode | null
|
prevVNode: VNode | null
|
||||||
|
@ -28,7 +28,6 @@ export { PublicShapeFlags as ShapeFlags } from './shapeFlags'
|
|||||||
export { getCurrentInstance } from './component'
|
export { getCurrentInstance } from './component'
|
||||||
|
|
||||||
// For custom renderers
|
// For custom renderers
|
||||||
export { createAppAPI } from './apiApp'
|
|
||||||
export { createRenderer } from './createRenderer'
|
export { createRenderer } from './createRenderer'
|
||||||
export {
|
export {
|
||||||
handleError,
|
handleError,
|
||||||
|
@ -7,17 +7,16 @@ import {
|
|||||||
extend
|
extend
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
import { ComponentInternalInstance, Data, SetupProxySymbol } from './component'
|
import { ComponentInternalInstance, Data, SetupProxySymbol } from './component'
|
||||||
import { HostNode } from './createRenderer'
|
|
||||||
import { RawSlots } from './componentSlots'
|
import { RawSlots } from './componentSlots'
|
||||||
import { PatchFlags } from './patchFlags'
|
import { PatchFlags } from './patchFlags'
|
||||||
import { ShapeFlags } from './shapeFlags'
|
import { ShapeFlags } from './shapeFlags'
|
||||||
import { isReactive } from '@vue/reactivity'
|
import { isReactive } from '@vue/reactivity'
|
||||||
import { AppContext } from './apiApp'
|
import { AppContext } from './apiApp'
|
||||||
|
|
||||||
export const Fragment = Symbol('Fragment')
|
export const Fragment = __DEV__ ? Symbol('Fragment') : Symbol()
|
||||||
export const Text = Symbol('Text')
|
export const Text = __DEV__ ? Symbol('Text') : Symbol()
|
||||||
export const Empty = Symbol('Empty')
|
export const Empty = __DEV__ ? Symbol('Empty') : Symbol()
|
||||||
export const Portal = Symbol('Portal')
|
export const Portal = __DEV__ ? Symbol('Portal') : Symbol()
|
||||||
|
|
||||||
export type VNodeTypes =
|
export type VNodeTypes =
|
||||||
| string
|
| string
|
||||||
@ -28,24 +27,42 @@ export type VNodeTypes =
|
|||||||
| typeof Text
|
| typeof Text
|
||||||
| typeof Empty
|
| typeof Empty
|
||||||
|
|
||||||
type VNodeChildAtom = VNode | string | number | boolean | null | void
|
type VNodeChildAtom<HostNode, HostElement> =
|
||||||
export interface VNodeChildren extends Array<VNodeChildren | VNodeChildAtom> {}
|
| VNode<HostNode, HostElement>
|
||||||
export type VNodeChild = VNodeChildAtom | VNodeChildren
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null
|
||||||
|
| void
|
||||||
|
|
||||||
export type NormalizedChildren = string | VNodeChildren | RawSlots | null
|
export interface VNodeChildren<HostNode = any, HostElement = any>
|
||||||
|
extends Array<
|
||||||
|
| VNodeChildren<HostNode, HostElement>
|
||||||
|
| VNodeChildAtom<HostNode, HostElement>
|
||||||
|
> {}
|
||||||
|
|
||||||
export interface VNode {
|
export type VNodeChild<HostNode = any, HostElement = any> =
|
||||||
|
| VNodeChildAtom<HostNode, HostElement>
|
||||||
|
| VNodeChildren<HostNode, HostElement>
|
||||||
|
|
||||||
|
export type NormalizedChildren<HostNode, HostElement> =
|
||||||
|
| string
|
||||||
|
| VNodeChildren<HostNode, HostElement>
|
||||||
|
| RawSlots
|
||||||
|
| null
|
||||||
|
|
||||||
|
export interface VNode<HostNode = any, HostElement = any> {
|
||||||
type: VNodeTypes
|
type: VNodeTypes
|
||||||
props: Record<any, any> | null
|
props: Record<any, any> | null
|
||||||
key: string | number | null
|
key: string | number | null
|
||||||
ref: string | Function | null
|
ref: string | Function | null
|
||||||
children: NormalizedChildren
|
children: NormalizedChildren<HostNode, HostElement>
|
||||||
component: ComponentInternalInstance | null
|
component: ComponentInternalInstance | null
|
||||||
|
|
||||||
// DOM
|
// DOM
|
||||||
el: HostNode | null
|
el: HostNode | null
|
||||||
anchor: HostNode | null // fragment anchor
|
anchor: HostNode | null // fragment anchor
|
||||||
target: HostNode | null // portal target
|
target: HostElement | null // portal target
|
||||||
|
|
||||||
// optimization only
|
// optimization only
|
||||||
shapeFlag: number
|
shapeFlag: number
|
||||||
@ -209,7 +226,7 @@ export function cloneVNode(vnode: VNode): VNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalizeVNode(child: VNodeChild): VNode {
|
export function normalizeVNode(child: VNodeChild<any, any>): VNode {
|
||||||
if (child == null) {
|
if (child == null) {
|
||||||
// empty placeholder
|
// empty placeholder
|
||||||
return createVNode(Empty)
|
return createVNode(Empty)
|
||||||
@ -241,7 +258,7 @@ export function normalizeChildren(vnode: VNode, children: unknown) {
|
|||||||
children = isString(children) ? children : children + ''
|
children = isString(children) ? children : children + ''
|
||||||
type = ShapeFlags.TEXT_CHILDREN
|
type = ShapeFlags.TEXT_CHILDREN
|
||||||
}
|
}
|
||||||
vnode.children = children as NormalizedChildren
|
vnode.children = children as NormalizedChildren<any, any>
|
||||||
vnode.shapeFlag |= type
|
vnode.shapeFlag |= type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
import { createRenderer, VNode, createAppAPI } from '@vue/runtime-core'
|
import { createRenderer } from '@vue/runtime-core'
|
||||||
import { nodeOps } from './nodeOps'
|
import { nodeOps } from './nodeOps'
|
||||||
import { patchProp } from './patchProp'
|
import { patchProp } from './patchProp'
|
||||||
|
|
||||||
export const render = createRenderer({
|
const { render, createApp } = createRenderer<Node, Element>({
|
||||||
patchProp,
|
patchProp,
|
||||||
...nodeOps
|
...nodeOps
|
||||||
}) as (vnode: VNode | null, container: HTMLElement) => void
|
})
|
||||||
|
|
||||||
export const createApp = createAppAPI(render)
|
export { render, createApp }
|
||||||
|
|
||||||
// re-export everything from core
|
// re-export everything from core
|
||||||
// h, Component, reactivity API, nextTick, flags & types
|
// h, Component, reactivity API, nextTick, flags & types
|
||||||
export * from '@vue/runtime-core'
|
export * from '@vue/runtime-core'
|
||||||
|
|
||||||
|
export interface ComponentPublicInstance {
|
||||||
|
$el: Element
|
||||||
|
}
|
||||||
|
@ -45,7 +45,7 @@ export function patchEvent(
|
|||||||
name: string,
|
name: string,
|
||||||
prevValue: EventValue | null,
|
prevValue: EventValue | null,
|
||||||
nextValue: EventValue | null,
|
nextValue: EventValue | null,
|
||||||
instance: ComponentInternalInstance | null
|
instance: ComponentInternalInstance | null = null
|
||||||
) {
|
) {
|
||||||
const invoker = prevValue && prevValue.invoker
|
const invoker = prevValue && prevValue.invoker
|
||||||
if (nextValue) {
|
if (nextValue) {
|
||||||
|
@ -36,5 +36,6 @@ export const nodeOps = {
|
|||||||
|
|
||||||
nextSibling: (node: Node): Node | null => node.nextSibling,
|
nextSibling: (node: Node): Node | null => node.nextSibling,
|
||||||
|
|
||||||
querySelector: (selector: string): Node | null => doc.querySelector(selector)
|
querySelector: (selector: string): Element | null =>
|
||||||
|
doc.querySelector(selector)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import { patchAttr } from './modules/attrs'
|
|||||||
import { patchDOMProp } from './modules/props'
|
import { patchDOMProp } from './modules/props'
|
||||||
import { patchEvent } from './modules/events'
|
import { patchEvent } from './modules/events'
|
||||||
import { isOn } from '@vue/shared'
|
import { isOn } from '@vue/shared'
|
||||||
import { VNode } from '@vue/runtime-core'
|
import { VNode, ComponentInternalInstance } from '@vue/runtime-core'
|
||||||
|
|
||||||
export function patchProp(
|
export function patchProp(
|
||||||
el: Element,
|
el: Element,
|
||||||
@ -13,7 +13,7 @@ export function patchProp(
|
|||||||
prevValue: any,
|
prevValue: any,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
prevChildren?: VNode[],
|
prevChildren?: VNode[],
|
||||||
parentComponent?: any,
|
parentComponent?: ComponentInternalInstance,
|
||||||
unmountChildren?: any
|
unmountChildren?: any
|
||||||
) {
|
) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { createRenderer, VNode, createAppAPI } from '@vue/runtime-core'
|
import { createRenderer, VNode } from '@vue/runtime-core'
|
||||||
import { nodeOps, TestElement } from './nodeOps'
|
import { nodeOps, TestNode, TestElement } from './nodeOps'
|
||||||
import { patchProp } from './patchProp'
|
import { patchProp } from './patchProp'
|
||||||
import { serializeInner } from './serialize'
|
import { serializeInner } from './serialize'
|
||||||
|
|
||||||
export const render = createRenderer({
|
const { render, createApp } = createRenderer<TestNode, TestElement>({
|
||||||
patchProp,
|
patchProp,
|
||||||
...nodeOps
|
...nodeOps
|
||||||
}) as (node: VNode | null, container: TestElement) => void
|
})
|
||||||
|
|
||||||
export const createApp = createAppAPI(render)
|
export { render, createApp }
|
||||||
|
|
||||||
// convenience for one-off render validations
|
// convenience for one-off render validations
|
||||||
export function renderToString(vnode: VNode) {
|
export function renderToString(vnode: VNode) {
|
||||||
|
@ -218,7 +218,7 @@ function nextSibling(node: TestNode): TestNode | null {
|
|||||||
return parent.children[i + 1] || null
|
return parent.children[i + 1] || null
|
||||||
}
|
}
|
||||||
|
|
||||||
function querySelector() {
|
function querySelector(): any {
|
||||||
throw new Error('querySelector not supported in test renderer.')
|
throw new Error('querySelector not supported in test renderer.')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user