refactor: adjust files

This commit is contained in:
Evan You
2019-02-26 18:04:52 -05:00
parent cbf95c642e
commit 77dae71062
10 changed files with 340 additions and 348 deletions

View File

@@ -0,0 +1,165 @@
import { VNode, createFragment, createTextVNode, cloneVNode } from './vdom'
import { ComponentInstance, FunctionalComponent } from './component'
import { resolveProps } from './componentProps'
import { handleError, ErrorTypes } from './errorHandling'
import { VNodeFlags, ChildrenFlags } from './flags'
import { EMPTY_OBJ, isArray, isObject } from '@vue/shared'
import { setCurrentInstance, unsetCurrentInstance } from './experimental/hooks'
export let isRendering = false
export function renderInstanceRoot(instance: ComponentInstance): VNode {
let vnode
const {
$options: { hooks },
render,
$proxy,
$props,
$slots,
$attrs,
$parentVNode
} = instance
try {
setCurrentInstance(instance)
if (hooks) {
instance._hookProps = hooks.call($proxy, $props) || null
}
if (__DEV__) {
isRendering = true
}
vnode = render.call($proxy, $props, $slots, $attrs, $parentVNode)
if (__DEV__) {
isRendering = false
}
unsetCurrentInstance()
} catch (err) {
handleError(err, instance, ErrorTypes.RENDER)
}
return normalizeComponentRoot(vnode, $parentVNode)
}
export function renderFunctionalRoot(vnode: VNode): VNode {
const render = vnode.tag as FunctionalComponent
const { 0: props, 1: attrs } = resolveProps(vnode.data, render.props)
let subTree
try {
subTree = render(props, vnode.slots || EMPTY_OBJ, attrs, vnode)
} catch (err) {
handleError(err, vnode, ErrorTypes.RENDER)
}
return normalizeComponentRoot(subTree, vnode)
}
function normalizeComponentRoot(
vnode: any,
componentVNode: VNode | null
): VNode {
if (vnode == null) {
vnode = createTextVNode('')
} else if (!isObject(vnode)) {
vnode = createTextVNode(vnode + '')
} else if (isArray(vnode)) {
if (vnode.length === 1) {
vnode = normalizeComponentRoot(vnode[0], componentVNode)
} else {
vnode = createFragment(vnode)
}
} else {
const { el, flags } = vnode
if (
componentVNode &&
(flags & VNodeFlags.COMPONENT || flags & VNodeFlags.ELEMENT)
) {
if (el) {
vnode = cloneVNode(vnode as VNode)
}
if (flags & VNodeFlags.COMPONENT) {
vnode.parentVNode = componentVNode
}
} else if (el) {
vnode = cloneVNode(vnode as VNode)
}
}
return vnode
}
export function shouldUpdateComponent(
prevVNode: VNode,
nextVNode: VNode
): boolean {
const { data: prevProps, childFlags: prevChildFlags } = prevVNode
const { data: nextProps, childFlags: nextChildFlags } = nextVNode
// If has different slots content, or has non-compiled slots,
// the child needs to be force updated.
if (
prevChildFlags !== nextChildFlags ||
(nextChildFlags & ChildrenFlags.DYNAMIC_SLOTS) > 0
) {
return true
}
if (prevProps === nextProps) {
return false
}
if (prevProps === null) {
return nextProps !== null
}
if (nextProps === null) {
return prevProps !== null
}
const nextKeys = Object.keys(nextProps)
if (nextKeys.length !== Object.keys(prevProps).length) {
return true
}
for (let i = 0; i < nextKeys.length; i++) {
const key = nextKeys[i]
if (nextProps[key] !== prevProps[key]) {
return true
}
}
return false
}
// DEV only
export function getReasonForComponentUpdate(
prevVNode: VNode,
nextVNode: VNode
): any {
const reasons = []
const { childFlags: prevChildFlags } = prevVNode
const { childFlags: nextChildFlags } = nextVNode
if (
prevChildFlags !== nextChildFlags ||
(nextChildFlags & ChildrenFlags.DYNAMIC_SLOTS) > 0
) {
reasons.push({
type: `slots may have changed`,
tip: `use function slots + $stable: true to avoid slot-triggered child updates.`
})
}
const prevProps = prevVNode.data || EMPTY_OBJ
const nextProps = nextVNode.data || EMPTY_OBJ
for (const key in nextProps) {
if (nextProps[key] !== prevProps[key]) {
reasons.push({
type: 'prop changed',
key,
value: nextProps[key],
oldValue: prevProps[key]
})
}
}
for (const key in prevProps) {
if (!(key in nextProps)) {
reasons.push({
type: 'prop changed',
key,
value: undefined,
oldValue: prevProps[key]
})
}
}
return {
type: 'triggered by parent',
reasons
}
}