// 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'
-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
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>()
)
}
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 = [
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
}
} 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 {
clonedData[key] = data[key]
}
}
- for (const key in extraData) {
- if (key === 'class') {
- clonedData.class = normalizeClass([clonedData.class, extraData.class])
- } else if (key === 'style') {
- clonedData.style = normalizeStyle([clonedData.style, extraData.style])
- } 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]
+ if (extraData !== EMPTY_OBJ) {
+ for (const key in extraData) {
+ if (key === 'class') {
+ clonedData.class = normalizeClass([
+ clonedData.class,
+ extraData.class
+ ])
+ } else if (key === 'style') {
+ clonedData.style = normalizeStyle([
+ clonedData.style,
+ extraData.style
+ ])
+ } 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]
+ }
}
}
}