wip(compiler-ssr): v-bind with static keys

This commit is contained in:
Evan You
2020-02-04 16:47:12 -05:00
parent e71781dcab
commit c059fc88b9
18 changed files with 189 additions and 92 deletions

View File

@@ -17,9 +17,11 @@ export function createSSRCompilerError(
}
export const enum SSRErrorCodes {
X_SSR_CUSTOM_DIRECTIVE_NO_TRANSFORM = DOMErrorCodes.__EXTEND_POINT__
X_SSR_CUSTOM_DIRECTIVE_NO_TRANSFORM = DOMErrorCodes.__EXTEND_POINT__,
X_SSR_UNSAFE_ATTR_NAME
}
export const SSRErrorMessages: { [code: number]: string } = {
[SSRErrorCodes.X_SSR_CUSTOM_DIRECTIVE_NO_TRANSFORM]: `Custom directive is missing corresponding SSR transform and will be ignored.`
[SSRErrorCodes.X_SSR_CUSTOM_DIRECTIVE_NO_TRANSFORM]: `Custom directive is missing corresponding SSR transform and will be ignored.`,
[SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME]: `Unsafe attribute name for SSR.`
}

View File

@@ -8,7 +8,8 @@ import {
transformExpression,
trackVForSlotScopes,
trackSlotScopes,
noopDirectiveTransform
noopDirectiveTransform,
transformBind
} from '@vue/compiler-dom'
import { ssrCodegenTransform } from './ssrCodegenTransform'
import { ssrTransformElement } from './transforms/ssrTransformElement'
@@ -16,9 +17,8 @@ import { ssrTransformComponent } from './transforms/ssrTransformComponent'
import { ssrTransformSlotOutlet } from './transforms/ssrTransformSlotOutlet'
import { ssrTransformIf } from './transforms/ssrVIf'
import { ssrTransformFor } from './transforms/ssrVFor'
import { ssrVBind } from './transforms/ssrVBind'
import { ssrVModel } from './transforms/ssrVModel'
import { ssrVShow } from './transforms/ssrVShow'
import { ssrTransformModel } from './transforms/ssrVModel'
import { ssrTransformShow } from './transforms/ssrVShow'
export function compile(
template: string,
@@ -54,9 +54,9 @@ export function compile(
ssrDirectiveTransforms: {
on: noopDirectiveTransform,
cloak: noopDirectiveTransform,
bind: ssrVBind,
model: ssrVModel,
show: ssrVShow,
bind: transformBind, // reusing core v-bind
model: ssrTransformModel,
show: ssrTransformShow,
...(options.ssrDirectiveTransforms || {}) // user transforms
}
})

View File

@@ -7,6 +7,7 @@ export const SSR_RENDER_CLASS = Symbol(`renderClass`)
export const SSR_RENDER_STYLE = Symbol(`renderStyle`)
export const SSR_RENDER_ATTRS = Symbol(`renderAttrs`)
export const SSR_RENDER_ATTR = Symbol(`renderAttr`)
export const SSR_RENDER_DYNAMIC_ATTR = Symbol(`renderDynamicAttr`)
export const SSR_RENDER_LIST = Symbol(`renderList`)
// Note: these are helpers imported from @vue/server-renderer
@@ -19,5 +20,6 @@ registerRuntimeHelpers({
[SSR_RENDER_STYLE]: `_renderStyle`,
[SSR_RENDER_ATTRS]: `_renderAttrs`,
[SSR_RENDER_ATTR]: `_renderAttr`,
[SSR_RENDER_DYNAMIC_ATTR]: `_renderDynamicAttr`,
[SSR_RENDER_LIST]: `_renderList`
})

View File

@@ -5,11 +5,18 @@ import {
TemplateLiteral,
createTemplateLiteral,
createInterpolation,
createCallExpression
createCallExpression,
createConditionalExpression,
createSimpleExpression
} from '@vue/compiler-dom'
import { escapeHtml } from '@vue/shared'
import { escapeHtml, isBooleanAttr, isSSRSafeAttrName } from '@vue/shared'
import { createSSRCompilerError, SSRErrorCodes } from '../errors'
import { SSR_RENDER_ATTR } from '../runtimeHelpers'
import {
SSR_RENDER_ATTR,
SSR_RENDER_CLASS,
SSR_RENDER_STYLE,
SSR_RENDER_DYNAMIC_ATTR
} from '../runtimeHelpers'
export const ssrTransformElement: NodeTransform = (node, context) => {
if (
@@ -66,12 +73,58 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
const { props } = directiveTransform(prop, node, context)
for (let j = 0; j < props.length; j++) {
const { key, value } = props[j]
openTag.push(
createCallExpression(context.helper(SSR_RENDER_ATTR), [
key,
value
])
)
if (key.type === NodeTypes.SIMPLE_EXPRESSION && key.isStatic) {
const attrName = key.content
// static key attr
if (attrName === 'class') {
openTag.push(
createCallExpression(context.helper(SSR_RENDER_CLASS), [
value
])
)
} else if (attrName === 'style') {
openTag.push(
createCallExpression(context.helper(SSR_RENDER_STYLE), [
value
])
)
} else if (isBooleanAttr(attrName)) {
openTag.push(
createConditionalExpression(
value,
createSimpleExpression(' ' + attrName, true),
createSimpleExpression('', true),
false /* no newline */
)
)
} else {
if (isSSRSafeAttrName(attrName)) {
openTag.push(
createCallExpression(context.helper(SSR_RENDER_ATTR), [
key,
value
])
)
} else {
context.onError(
createSSRCompilerError(
SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME,
key.loc
)
)
}
}
} else {
// dynamic key attr
// this branch is only encountered for custom directive
// transforms that returns properties with dynamic keys
openTag.push(
createCallExpression(
context.helper(SSR_RENDER_DYNAMIC_ATTR),
[key, value]
)
)
}
}
} else {
// no corresponding ssr directive transform found.

View File

@@ -1,18 +0,0 @@
import { DirectiveTransform, createObjectProperty } from '@vue/compiler-dom'
export const ssrVBind: DirectiveTransform = (dir, node, context) => {
if (!dir.exp) {
// error
return { props: [] }
} else {
// TODO modifiers
return {
props: [
createObjectProperty(
dir.arg!, // v-bind="obj" is handled separately
dir.exp
)
]
}
}
}

View File

@@ -1,6 +1,6 @@
import { DirectiveTransform } from '@vue/compiler-dom'
export const ssrVModel: DirectiveTransform = (dir, node, context) => {
export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
return {
props: []
}

View File

@@ -1,6 +1,6 @@
import { DirectiveTransform } from '@vue/compiler-dom'
export const ssrVShow: DirectiveTransform = (dir, node, context) => {
export const ssrTransformShow: DirectiveTransform = (dir, node, context) => {
return {
props: []
}