wip: vnodeXXX directive hooks

This commit is contained in:
Evan You 2019-08-31 17:06:39 -04:00
parent 1c6ecf4144
commit 0f0ca4ae7c
4 changed files with 34 additions and 4 deletions

View File

@ -35,6 +35,7 @@ import { resolveSlots } from './componentSlots'
import { PatchFlags } from './patchFlags' 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'
const prodEffectOptions = { const prodEffectOptions = {
scheduler: queueJob scheduler: queueJob
@ -248,6 +249,7 @@ export function createRenderer(options: RendererOptions) {
if (isReservedProp(key)) continue if (isReservedProp(key)) continue
hostPatchProp(el, key, props[key], null, isSVG) hostPatchProp(el, key, props[key], null, isSVG)
} }
invokeDirectiveHook(props.vnodeBeforeMount, parentComponent, vnode)
} }
if (shapeFlag & ShapeFlags.TEXT_CHILDREN) { if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
hostSetElementText(el, vnode.children as string) hostSetElementText(el, vnode.children as string)
@ -261,6 +263,9 @@ export function createRenderer(options: RendererOptions) {
) )
} }
hostInsert(el, container, anchor) hostInsert(el, container, anchor)
if (props != null) {
invokeDirectiveHook(props.vnodeMounted, parentComponent, vnode)
}
} }
function mountChildren( function mountChildren(

View File

@ -13,13 +13,14 @@ return applyDirectives(
*/ */
import { VNode, cloneVNode } from './vnode' import { VNode, cloneVNode } from './vnode'
import { extend } from '@vue/shared' import { extend, isArray, isFunction } from '@vue/shared'
import { warn } from './warning' import { warn } from './warning'
import { import {
ComponentInstance, ComponentInstance,
currentRenderingInstance, currentRenderingInstance,
ComponentRenderProxy ComponentRenderProxy
} from './component' } from './component'
import { callWithAsyncErrorHandling, ErrorTypes } from './errorHandling'
interface DirectiveBinding { interface DirectiveBinding {
instance: ComponentRenderProxy | null instance: ComponentRenderProxy | null
@ -120,3 +121,26 @@ export function resolveDirective(name: string): Directive {
// TODO // TODO
return {} as any return {} as any
} }
export function invokeDirectiveHook(
hook: Function | Function[],
instance: ComponentInstance | null,
vnode: VNode
) {
if (hook == null) {
return
}
const args = [vnode]
if (isArray(hook)) {
for (let i = 0; i < hook.length; i++) {
callWithAsyncErrorHandling(
hook[i],
instance,
ErrorTypes.DIRECTIVE_HOOK,
args
)
}
} else if (isFunction(hook)) {
callWithAsyncErrorHandling(hook, instance, ErrorTypes.DIRECTIVE_HOOK, args)
}
}

View File

@ -12,6 +12,7 @@ export const enum ErrorTypes {
WATCH_CLEANUP, WATCH_CLEANUP,
NATIVE_EVENT_HANDLER, NATIVE_EVENT_HANDLER,
COMPONENT_EVENT_HANDLER, COMPONENT_EVENT_HANDLER,
DIRECTIVE_HOOK,
SCHEDULER SCHEDULER
} }
@ -36,6 +37,7 @@ export const ErrorTypeStrings: Record<number | string, string> = {
[ErrorTypes.WATCH_CLEANUP]: 'watcher cleanup function', [ErrorTypes.WATCH_CLEANUP]: 'watcher cleanup function',
[ErrorTypes.NATIVE_EVENT_HANDLER]: 'native event handler', [ErrorTypes.NATIVE_EVENT_HANDLER]: 'native event handler',
[ErrorTypes.COMPONENT_EVENT_HANDLER]: 'component event handler', [ErrorTypes.COMPONENT_EVENT_HANDLER]: 'component event handler',
[ErrorTypes.DIRECTIVE_HOOK]: 'directive hook',
[ErrorTypes.SCHEDULER]: [ErrorTypes.SCHEDULER]:
'scheduler flush. This may be a Vue internals bug. ' + 'scheduler flush. This may be a Vue internals bug. ' +
'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue' 'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue'

View File

@ -3,8 +3,6 @@ export const EMPTY_ARR: [] = []
export const NOOP = () => {} export const NOOP = () => {}
export const reservedPropRE = /^(?:key|ref|slots)$|^vnode/
export const isOn = (key: string) => key[0] === 'o' && key[1] === 'n' export const isOn = (key: string) => key[0] === 'o' && key[1] === 'n'
export const extend = <T extends object, U extends object>( export const extend = <T extends object, U extends object>(
@ -24,8 +22,9 @@ export const isString = (val: any): val is string => typeof val === 'string'
export const isObject = (val: any): val is Record<any, any> => export const isObject = (val: any): val is Record<any, any> =>
val !== null && typeof val === 'object' val !== null && typeof val === 'object'
const vnodeHooksRE = /^vnode/
export const isReservedProp = (key: string): boolean => export const isReservedProp = (key: string): boolean =>
key === 'key' || key === 'ref' key === 'key' || key === 'ref' || vnodeHooksRE.test(key)
const camelizeRE = /-(\w)/g const camelizeRE = /-(\w)/g
export const camelize = (str: string): string => { export const camelize = (str: string): string => {