Skip to content

Commit c450ede

Browse files
committed
feat(ssr): support getSSRProps for vnode directives
1 parent a46f3b3 commit c450ede

File tree

5 files changed

+458
-6
lines changed

5 files changed

+458
-6
lines changed

packages/runtime-core/src/directives.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ return withDirectives(h(comp), [
1414
import { VNode } from './vnode'
1515
import { isFunction, EMPTY_OBJ, makeMap, EMPTY_ARR } from '@vue/shared'
1616
import { warn } from './warning'
17-
import { ComponentInternalInstance } from './component'
17+
import { ComponentInternalInstance, Data } from './component'
1818
import { currentRenderingInstance } from './componentRenderUtils'
1919
import { callWithAsyncErrorHandling, ErrorCodes } from './errorHandling'
2020
import { ComponentPublicInstance } from './componentProxy'
@@ -35,13 +35,19 @@ export type DirectiveHook<T = any> = (
3535
prevVNode: VNode<any, T> | null
3636
) => void
3737

38+
export type SSRDirectiveHook = (
39+
binding: DirectiveBinding,
40+
vnode: VNode
41+
) => Data | undefined
42+
3843
export interface ObjectDirective<T = any> {
3944
beforeMount?: DirectiveHook<T>
4045
mounted?: DirectiveHook<T>
4146
beforeUpdate?: DirectiveHook<T>
4247
updated?: DirectiveHook<T>
4348
beforeUnmount?: DirectiveHook<T>
4449
unmounted?: DirectiveHook<T>
50+
getSSRProps?: SSRDirectiveHook
4551
}
4652

4753
export type FunctionDirective<T = any> = DirectiveHook<T>
@@ -81,7 +87,7 @@ const directiveToVnodeHooksMap = /*#__PURE__*/ [
8187
const prevBindings = prevVnode ? prevVnode.dirs! : EMPTY_ARR
8288
for (let i = 0; i < bindings.length; i++) {
8389
const binding = bindings[i]
84-
const hook = binding.dir[key]
90+
const hook = binding.dir[key] as DirectiveHook
8591
if (hook != null) {
8692
if (prevVnode != null) {
8793
binding.oldValue = prevBindings[i].value

packages/runtime-dom/src/directives/vModel.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ function callModelHook(
218218
binding: DirectiveBinding,
219219
vnode: VNode,
220220
prevVNode: VNode | null,
221-
hook: keyof ObjectDirective
221+
hook: 'beforeMount' | 'mounted' | 'beforeUpdate' | 'updated'
222222
) {
223223
let modelToUse: ObjectDirective
224224
switch (el.tagName) {
@@ -243,3 +243,24 @@ function callModelHook(
243243
const fn = modelToUse[hook]
244244
fn && fn(el, binding, vnode, prevVNode)
245245
}
246+
247+
// SSR vnode transforms
248+
if (__NODE_JS__) {
249+
vModelText.getSSRProps = ({ value }) => ({ value })
250+
251+
vModelRadio.getSSRProps = ({ value }, vnode) => {
252+
if (vnode.props && looseEqual(vnode.props.value, value)) {
253+
return { checked: true }
254+
}
255+
}
256+
257+
vModelCheckbox.getSSRProps = ({ value }, vnode) => {
258+
if (isArray(value)) {
259+
if (vnode.props && looseIndexOf(value, vnode.props.value) > -1) {
260+
return { checked: true }
261+
}
262+
} else if (value) {
263+
return { checked: true }
264+
}
265+
}
266+
}

packages/runtime-dom/src/directives/vShow.ts

+8
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ export const vShow: ObjectDirective<VShowElement> = {
4040
}
4141
}
4242

43+
if (__NODE_JS__) {
44+
vShow.getSSRProps = ({ value }) => {
45+
if (!value) {
46+
return { style: { display: 'none' } }
47+
}
48+
}
49+
}
50+
4351
function setDisplay(el: VShowElement, value: unknown): void {
4452
el.style.display = value ? el._vod : 'none'
4553
}

0 commit comments

Comments
 (0)