feat: directives
This commit is contained in:
parent
0f0ca4ae7c
commit
9b428c6d83
@ -249,7 +249,9 @@ export function createRenderer(options: RendererOptions) {
|
||||
if (isReservedProp(key)) continue
|
||||
hostPatchProp(el, key, props[key], null, isSVG)
|
||||
}
|
||||
invokeDirectiveHook(props.vnodeBeforeMount, parentComponent, vnode)
|
||||
if (props.vnodeBeforeMount != null) {
|
||||
invokeDirectiveHook(props.vnodeBeforeMount, parentComponent, vnode)
|
||||
}
|
||||
}
|
||||
if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
|
||||
hostSetElementText(el, vnode.children as string)
|
||||
@ -263,8 +265,10 @@ export function createRenderer(options: RendererOptions) {
|
||||
)
|
||||
}
|
||||
hostInsert(el, container, anchor)
|
||||
if (props != null) {
|
||||
invokeDirectiveHook(props.vnodeMounted, parentComponent, vnode)
|
||||
if (props != null && props.vnodeMounted != null) {
|
||||
queuePostFlushCb(() => {
|
||||
invokeDirectiveHook(props.vnodeMounted, parentComponent, vnode)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,6 +298,10 @@ export function createRenderer(options: RendererOptions) {
|
||||
const oldProps = (n1 && n1.props) || EMPTY_OBJ
|
||||
const newProps = n2.props || EMPTY_OBJ
|
||||
|
||||
if (newProps.vnodeBeforeUpdate != null) {
|
||||
invokeDirectiveHook(newProps.vnodeBeforeUpdate, parentComponent, n2)
|
||||
}
|
||||
|
||||
if (patchFlag) {
|
||||
// the presence of a patchFlag means this element's render code was
|
||||
// generated by the compiler and can take the fast path.
|
||||
@ -379,6 +387,12 @@ export function createRenderer(options: RendererOptions) {
|
||||
// full diff
|
||||
patchChildren(n1, n2, el, null, parentComponent, isSVG)
|
||||
}
|
||||
|
||||
if (newProps.vnodeUpdated != null) {
|
||||
queuePostFlushCb(() => {
|
||||
invokeDirectiveHook(newProps.vnodeUpdated, parentComponent, n2)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function patchProps(
|
||||
@ -1017,27 +1031,37 @@ export function createRenderer(options: RendererOptions) {
|
||||
parentComponent: ComponentInstance | null,
|
||||
doRemove?: boolean
|
||||
) {
|
||||
const {
|
||||
props,
|
||||
ref,
|
||||
type,
|
||||
component,
|
||||
children,
|
||||
dynamicChildren,
|
||||
shapeFlag,
|
||||
anchor
|
||||
} = vnode
|
||||
|
||||
// unset ref
|
||||
if (vnode.ref !== null && parentComponent !== null) {
|
||||
setRef(vnode.ref, null, parentComponent, null)
|
||||
if (ref !== null && parentComponent !== null) {
|
||||
setRef(ref, null, parentComponent, null)
|
||||
}
|
||||
|
||||
const instance = vnode.component
|
||||
if (instance != null) {
|
||||
unmountComponent(instance, doRemove)
|
||||
if (component != null) {
|
||||
unmountComponent(component, doRemove)
|
||||
return
|
||||
}
|
||||
|
||||
const shouldRemoveChildren = vnode.type === Fragment && doRemove
|
||||
if (vnode.dynamicChildren != null) {
|
||||
if (props != null && props.vnodeBeforeUnmount != null) {
|
||||
invokeDirectiveHook(props.vnodeBeforeUnmount, parentComponent, vnode)
|
||||
}
|
||||
|
||||
const shouldRemoveChildren = type === Fragment && doRemove
|
||||
if (dynamicChildren != null) {
|
||||
unmountChildren(dynamicChildren, parentComponent, shouldRemoveChildren)
|
||||
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||
unmountChildren(
|
||||
vnode.dynamicChildren,
|
||||
parentComponent,
|
||||
shouldRemoveChildren
|
||||
)
|
||||
} else if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||
unmountChildren(
|
||||
vnode.children as VNode[],
|
||||
children as VNode[],
|
||||
parentComponent,
|
||||
shouldRemoveChildren
|
||||
)
|
||||
@ -1045,7 +1069,13 @@ export function createRenderer(options: RendererOptions) {
|
||||
|
||||
if (doRemove) {
|
||||
hostRemove(vnode.el)
|
||||
if (vnode.anchor != null) hostRemove(vnode.anchor)
|
||||
if (anchor != null) hostRemove(anchor)
|
||||
}
|
||||
|
||||
if (props != null && props.vnodeUnmounted != null) {
|
||||
queuePostFlushCb(() => {
|
||||
invokeDirectiveHook(props.vnodeUnmounted, parentComponent, vnode)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,9 +127,6 @@ export function invokeDirectiveHook(
|
||||
instance: ComponentInstance | null,
|
||||
vnode: VNode
|
||||
) {
|
||||
if (hook == null) {
|
||||
return
|
||||
}
|
||||
const args = [vnode]
|
||||
if (isArray(hook)) {
|
||||
for (let i = 0; i < hook.length; i++) {
|
||||
|
@ -45,21 +45,22 @@ export const enum PatchFlags {
|
||||
// exclusive with CLASS, STYLE and PROPS.
|
||||
FULL_PROPS = 1 << 4,
|
||||
|
||||
// Indicates an element that only needs non-props patching, e.g. ref or
|
||||
// directives (vnodeXXX hooks). It simply marks the vnode as "need patch",
|
||||
// since every pathced vnode checks for refs and vnodeXXX hooks.
|
||||
NEED_PATCH = 1 << 5,
|
||||
|
||||
// Indicates a fragment or element with keyed or partially-keyed v-for
|
||||
// children
|
||||
KEYED = 1 << 5,
|
||||
KEYED = 1 << 6,
|
||||
|
||||
// Indicates a fragment or element that contains unkeyed v-for children
|
||||
UNKEYED = 1 << 6,
|
||||
UNKEYED = 1 << 7,
|
||||
|
||||
// Indicates a component with dynamic slots (e.g. slot that references a v-for
|
||||
// iterated value, or dynamic slot names).
|
||||
// Components with this flag are always force updated.
|
||||
DYNAMIC_SLOTS = 1 << 7,
|
||||
|
||||
// Indicates an element with ref. This includes static string refs because the
|
||||
// refs object is refreshed on each update and all refs need to set again.
|
||||
REF = 1 << 8
|
||||
DYNAMIC_SLOTS = 1 << 8
|
||||
}
|
||||
|
||||
// runtime object for public consumption
|
||||
@ -68,8 +69,8 @@ export const PublicPatchFlags = {
|
||||
CLASS: PatchFlags.CLASS,
|
||||
STYLE: PatchFlags.STYLE,
|
||||
PROPS: PatchFlags.PROPS,
|
||||
NEED_PATCH: PatchFlags.NEED_PATCH,
|
||||
FULL_PROPS: PatchFlags.FULL_PROPS,
|
||||
KEYED: PatchFlags.KEYED,
|
||||
UNKEYED: PatchFlags.UNKEYED,
|
||||
REF: PatchFlags.REF
|
||||
UNKEYED: PatchFlags.UNKEYED
|
||||
}
|
||||
|
@ -157,8 +157,8 @@ export function createVNode(
|
||||
|
||||
normalizeChildren(vnode, children)
|
||||
|
||||
// presence of a patch flag indicates this node is dynamic
|
||||
// component nodes also should always be tracked, because even if the
|
||||
// presence of a patch flag indicates this node needs patching on updates.
|
||||
// component nodes also should always be patched, because even if the
|
||||
// component doesn't need to update, it needs to persist the instance on to
|
||||
// the next vnode so that it can be properly unmounted later.
|
||||
if (
|
||||
|
Loading…
x
Reference in New Issue
Block a user