refactor: tweak applyDirectives
This commit is contained in:
parent
1a68bcb4a7
commit
b527705928
@ -15,7 +15,7 @@ export { createComponentInstance } from './componentUtils'
|
|||||||
|
|
||||||
// Optional APIs
|
// Optional APIs
|
||||||
// these are imported on-demand and can be tree-shaken
|
// these are imported on-demand and can be tree-shaken
|
||||||
export { applyDirective } from './optional/directive'
|
export { applyDirectives } from './optional/directive'
|
||||||
export { Provide, Inject } from './optional/context'
|
export { Provide, Inject } from './optional/context'
|
||||||
export { createAsyncComponent } from './optional/asyncComponent'
|
export { createAsyncComponent } from './optional/asyncComponent'
|
||||||
export { KeepAlive } from './optional/keepAlive'
|
export { KeepAlive } from './optional/keepAlive'
|
||||||
|
@ -1,5 +1,21 @@
|
|||||||
import { VNode } from '../vdom'
|
/**
|
||||||
|
Runtime helper for applying directives to a vnode. Example usage:
|
||||||
|
|
||||||
|
const comp = resolveComponent(this, 'comp')
|
||||||
|
const foo = resolveDirective(this, 'foo')
|
||||||
|
const bar = resolveDirective(this, 'bar')
|
||||||
|
|
||||||
|
return applyDirectives(
|
||||||
|
h(comp),
|
||||||
|
this,
|
||||||
|
[foo, this.x],
|
||||||
|
[bar, this.y]
|
||||||
|
)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { VNode, cloneVNode, VNodeData } from '../vdom'
|
||||||
import { ComponentInstance } from '../component'
|
import { ComponentInstance } from '../component'
|
||||||
|
import { EMPTY_OBJ } from '../utils'
|
||||||
|
|
||||||
interface DirectiveBinding {
|
interface DirectiveBinding {
|
||||||
instance: ComponentInstance
|
instance: ComponentInstance
|
||||||
@ -30,14 +46,13 @@ type DirectiveModifiers = Record<string, boolean>
|
|||||||
const valueCache = new WeakMap<Directive, WeakMap<any, any>>()
|
const valueCache = new WeakMap<Directive, WeakMap<any, any>>()
|
||||||
|
|
||||||
export function applyDirective(
|
export function applyDirective(
|
||||||
vnode: VNode,
|
data: VNodeData,
|
||||||
instance: ComponentInstance,
|
instance: ComponentInstance,
|
||||||
directive: Directive,
|
directive: Directive,
|
||||||
value?: any,
|
value?: any,
|
||||||
arg?: string,
|
arg?: string,
|
||||||
modifiers?: DirectiveModifiers
|
modifiers?: DirectiveModifiers
|
||||||
): VNode {
|
) {
|
||||||
const data = vnode.data || (vnode.data = {})
|
|
||||||
let valueCacheForDir = valueCache.get(directive) as WeakMap<VNode, any>
|
let valueCacheForDir = valueCache.get(directive) as WeakMap<VNode, any>
|
||||||
if (!valueCacheForDir) {
|
if (!valueCacheForDir) {
|
||||||
valueCacheForDir = new WeakMap<VNode, any>()
|
valueCacheForDir = new WeakMap<VNode, any>()
|
||||||
@ -67,9 +82,10 @@ export function applyDirective(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
const existing = data[hookKey]
|
const existing = data[hookKey]
|
||||||
data[hookKey] = existing ? [].concat(existing, vnodeHook as any) : vnodeHook
|
data[hookKey] = existing
|
||||||
|
? [].concat(existing as any, vnodeHook as any)
|
||||||
|
: vnodeHook
|
||||||
}
|
}
|
||||||
return vnode
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type DirectiveArguments = [
|
type DirectiveArguments = [
|
||||||
@ -84,8 +100,9 @@ export function applyDirectives(
|
|||||||
instance: ComponentInstance,
|
instance: ComponentInstance,
|
||||||
...directives: DirectiveArguments
|
...directives: DirectiveArguments
|
||||||
) {
|
) {
|
||||||
|
vnode = cloneVNode(vnode, EMPTY_OBJ)
|
||||||
for (let i = 0; i < directives.length; i++) {
|
for (let i = 0; i < directives.length; i++) {
|
||||||
applyDirective(vnode, instance, ...directives[i])
|
applyDirective(vnode.data as VNodeData, instance, ...directives[i])
|
||||||
}
|
}
|
||||||
return vnode
|
return vnode
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
} from './component'
|
} from './component'
|
||||||
import { VNodeFlags, ChildrenFlags } from './flags'
|
import { VNodeFlags, ChildrenFlags } from './flags'
|
||||||
import { createComponentClassFromOptions } from './componentUtils'
|
import { createComponentClassFromOptions } from './componentUtils'
|
||||||
import { normalizeClass, normalizeStyle, handlersRE } from './utils'
|
import { normalizeClass, normalizeStyle, handlersRE, EMPTY_OBJ } from './utils'
|
||||||
|
|
||||||
// Vue core is platform agnostic, so we are not using Element for "DOM" nodes.
|
// Vue core is platform agnostic, so we are not using Element for "DOM" nodes.
|
||||||
export interface RenderNode {
|
export interface RenderNode {
|
||||||
@ -264,19 +264,27 @@ export function cloneVNode(vnode: VNode, extraData?: VNodeData): VNode {
|
|||||||
clonedData[key] = data[key]
|
clonedData[key] = data[key]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const key in extraData) {
|
if (extraData !== EMPTY_OBJ) {
|
||||||
if (key === 'class') {
|
for (const key in extraData) {
|
||||||
clonedData.class = normalizeClass([clonedData.class, extraData.class])
|
if (key === 'class') {
|
||||||
} else if (key === 'style') {
|
clonedData.class = normalizeClass([
|
||||||
clonedData.style = normalizeStyle([clonedData.style, extraData.style])
|
clonedData.class,
|
||||||
} else if (handlersRE.test(key)) {
|
extraData.class
|
||||||
// on*, nativeOn*, vnode*
|
])
|
||||||
const existing = clonedData[key]
|
} else if (key === 'style') {
|
||||||
clonedData[key] = existing
|
clonedData.style = normalizeStyle([
|
||||||
? [].concat(existing, extraData[key])
|
clonedData.style,
|
||||||
: extraData[key]
|
extraData.style
|
||||||
} else {
|
])
|
||||||
clonedData[key] = extraData[key]
|
} else if (handlersRE.test(key)) {
|
||||||
|
// on*, nativeOn*, vnode*
|
||||||
|
const existing = clonedData[key]
|
||||||
|
clonedData[key] = existing
|
||||||
|
? [].concat(existing, extraData[key])
|
||||||
|
: extraData[key]
|
||||||
|
} else {
|
||||||
|
clonedData[key] = extraData[key]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user