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