From 0f0ca4ae7c2bb68b0b901e88ee1d9dc2f8bb6ddf Mon Sep 17 00:00:00 2001 From: Evan You Date: Sat, 31 Aug 2019 17:06:39 -0400 Subject: [PATCH] wip: vnodeXXX directive hooks --- packages/runtime-core/src/createRenderer.ts | 5 ++++ packages/runtime-core/src/directives.ts | 26 ++++++++++++++++++++- packages/runtime-core/src/errorHandling.ts | 2 ++ packages/shared/src/index.ts | 5 ++-- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/packages/runtime-core/src/createRenderer.ts b/packages/runtime-core/src/createRenderer.ts index 91221e5500..7870299ad2 100644 --- a/packages/runtime-core/src/createRenderer.ts +++ b/packages/runtime-core/src/createRenderer.ts @@ -35,6 +35,7 @@ import { resolveSlots } from './componentSlots' import { PatchFlags } from './patchFlags' import { ShapeFlags } from './shapeFlags' import { pushWarningContext, popWarningContext, warn } from './warning' +import { invokeDirectiveHook } from './directives' const prodEffectOptions = { scheduler: queueJob @@ -248,6 +249,7 @@ export function createRenderer(options: RendererOptions) { if (isReservedProp(key)) continue hostPatchProp(el, key, props[key], null, isSVG) } + invokeDirectiveHook(props.vnodeBeforeMount, parentComponent, vnode) } if (shapeFlag & ShapeFlags.TEXT_CHILDREN) { hostSetElementText(el, vnode.children as string) @@ -261,6 +263,9 @@ export function createRenderer(options: RendererOptions) { ) } hostInsert(el, container, anchor) + if (props != null) { + invokeDirectiveHook(props.vnodeMounted, parentComponent, vnode) + } } function mountChildren( diff --git a/packages/runtime-core/src/directives.ts b/packages/runtime-core/src/directives.ts index 46a697e624..bb799aa82e 100644 --- a/packages/runtime-core/src/directives.ts +++ b/packages/runtime-core/src/directives.ts @@ -13,13 +13,14 @@ return applyDirectives( */ import { VNode, cloneVNode } from './vnode' -import { extend } from '@vue/shared' +import { extend, isArray, isFunction } from '@vue/shared' import { warn } from './warning' import { ComponentInstance, currentRenderingInstance, ComponentRenderProxy } from './component' +import { callWithAsyncErrorHandling, ErrorTypes } from './errorHandling' interface DirectiveBinding { instance: ComponentRenderProxy | null @@ -120,3 +121,26 @@ export function resolveDirective(name: string): Directive { // TODO 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) + } +} diff --git a/packages/runtime-core/src/errorHandling.ts b/packages/runtime-core/src/errorHandling.ts index 7cad6a3525..0f02732d8d 100644 --- a/packages/runtime-core/src/errorHandling.ts +++ b/packages/runtime-core/src/errorHandling.ts @@ -12,6 +12,7 @@ export const enum ErrorTypes { WATCH_CLEANUP, NATIVE_EVENT_HANDLER, COMPONENT_EVENT_HANDLER, + DIRECTIVE_HOOK, SCHEDULER } @@ -36,6 +37,7 @@ export const ErrorTypeStrings: Record = { [ErrorTypes.WATCH_CLEANUP]: 'watcher cleanup function', [ErrorTypes.NATIVE_EVENT_HANDLER]: 'native event handler', [ErrorTypes.COMPONENT_EVENT_HANDLER]: 'component event handler', + [ErrorTypes.DIRECTIVE_HOOK]: 'directive hook', [ErrorTypes.SCHEDULER]: 'scheduler flush. This may be a Vue internals bug. ' + 'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue' diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 9e857a64ef..469826aebd 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -3,8 +3,6 @@ export const EMPTY_ARR: [] = [] export const NOOP = () => {} -export const reservedPropRE = /^(?:key|ref|slots)$|^vnode/ - export const isOn = (key: string) => key[0] === 'o' && key[1] === 'n' export const extend = ( @@ -24,8 +22,9 @@ export const isString = (val: any): val is string => typeof val === 'string' export const isObject = (val: any): val is Record => val !== null && typeof val === 'object' +const vnodeHooksRE = /^vnode/ export const isReservedProp = (key: string): boolean => - key === 'key' || key === 'ref' + key === 'key' || key === 'ref' || vnodeHooksRE.test(key) const camelizeRE = /-(\w)/g export const camelize = (str: string): string => { -- 2.47.3