refactor: tweak applyDirectives

This commit is contained in:
Evan You 2018-10-09 18:55:16 -04:00
parent 1a68bcb4a7
commit b527705928
3 changed files with 47 additions and 22 deletions

View File

@ -15,7 +15,7 @@ export { createComponentInstance } from './componentUtils'
// Optional APIs
// 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 { createAsyncComponent } from './optional/asyncComponent'
export { KeepAlive } from './optional/keepAlive'

View File

@ -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 { EMPTY_OBJ } from '../utils'
interface DirectiveBinding {
instance: ComponentInstance
@ -30,14 +46,13 @@ type DirectiveModifiers = Record<string, boolean>
const valueCache = new WeakMap<Directive, WeakMap<any, any>>()
export function applyDirective(
vnode: VNode,
data: VNodeData,
instance: ComponentInstance,
directive: Directive,
value?: any,
arg?: string,
modifiers?: DirectiveModifiers
): VNode {
const data = vnode.data || (vnode.data = {})
) {
let valueCacheForDir = valueCache.get(directive) as WeakMap<VNode, any>
if (!valueCacheForDir) {
valueCacheForDir = new WeakMap<VNode, any>()
@ -67,9 +82,10 @@ export function applyDirective(
)
}
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 = [
@ -84,8 +100,9 @@ export function applyDirectives(
instance: ComponentInstance,
...directives: DirectiveArguments
) {
vnode = cloneVNode(vnode, EMPTY_OBJ)
for (let i = 0; i < directives.length; i++) {
applyDirective(vnode, instance, ...directives[i])
applyDirective(vnode.data as VNodeData, instance, ...directives[i])
}
return vnode
}

View File

@ -5,7 +5,7 @@ import {
} from './component'
import { VNodeFlags, ChildrenFlags } from './flags'
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.
export interface RenderNode {
@ -264,11 +264,18 @@ export function cloneVNode(vnode: VNode, extraData?: VNodeData): VNode {
clonedData[key] = data[key]
}
}
if (extraData !== EMPTY_OBJ) {
for (const key in extraData) {
if (key === 'class') {
clonedData.class = normalizeClass([clonedData.class, extraData.class])
clonedData.class = normalizeClass([
clonedData.class,
extraData.class
])
} else if (key === 'style') {
clonedData.style = normalizeStyle([clonedData.style, extraData.style])
clonedData.style = normalizeStyle([
clonedData.style,
extraData.style
])
} else if (handlersRE.test(key)) {
// on*, nativeOn*, vnode*
const existing = clonedData[key]
@ -280,6 +287,7 @@ export function cloneVNode(vnode: VNode, extraData?: VNodeData): VNode {
}
}
}
}
return createVNode(
flags,
vnode.tag,