mirror of https://github.com/vuejs/core.git
fix(compiler-ssr): add selected option attribute from select value
This commit is contained in:
parent
ba391f5fdf
commit
67ad86174d
|
@ -1,5 +1,7 @@
|
||||||
import { getCompiledString } from './utils'
|
import { getCompiledString } from './utils'
|
||||||
import { compile } from '../src'
|
import { compile } from '../src'
|
||||||
|
import { renderToString } from '@vue/server-renderer'
|
||||||
|
import { createApp } from '@vue/runtime-dom'
|
||||||
|
|
||||||
describe('ssr: element', () => {
|
describe('ssr: element', () => {
|
||||||
test('basic elements', () => {
|
test('basic elements', () => {
|
||||||
|
@ -71,6 +73,160 @@ describe('ssr: element', () => {
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('<select> with dynamic value assigns `selected` option attribute', async () => {
|
||||||
|
expect(
|
||||||
|
getCompiledString(
|
||||||
|
`<select :value="selectValue"><option value="1"></option></select>`,
|
||||||
|
),
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"\`<select><option value="1"\${
|
||||||
|
(_ssrIncludeBooleanAttr((Array.isArray(_ctx.selectValue))
|
||||||
|
? _ssrLooseContain(_ctx.selectValue, "1")
|
||||||
|
: _ssrLooseEqual(_ctx.selectValue, "1"))) ? " selected" : ""
|
||||||
|
}></option></select>\`"
|
||||||
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await renderToString(
|
||||||
|
createApp({
|
||||||
|
data: () => ({ selected: 2 }),
|
||||||
|
template: `<div><select :value="selected"><option value="1">1</option><option value="2">2</option></select></div>`,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
).toMatchInlineSnapshot(
|
||||||
|
`"<div><select><option value="1">1</option><option value="2" selected>2</option></select></div>"`,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('<select> with static value assigns `selected` option attribute', async () => {
|
||||||
|
expect(
|
||||||
|
getCompiledString(
|
||||||
|
`<select value="selectValue"><option value="1"></option></select>`,
|
||||||
|
),
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"\`<select><option value="1"\${
|
||||||
|
(_ssrIncludeBooleanAttr(_ssrLooseEqual("selectValue", "1"))) ? " selected" : ""
|
||||||
|
}></option></select>\`"
|
||||||
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await renderToString(
|
||||||
|
createApp({
|
||||||
|
template: `<div><select value="2"><option value="1">1</option><option value="2">2</option></select></div>`,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
).toMatchInlineSnapshot(
|
||||||
|
`"<div><select><option value="1">1</option><option value="2" selected>2</option></select></div>"`,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('<select> with dynamic v-bind assigns `selected` option attribute', async () => {
|
||||||
|
expect(
|
||||||
|
compile(`<select v-bind="obj"><option value="1"></option></select>`)
|
||||||
|
.code,
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { mergeProps: _mergeProps } = require("vue")
|
||||||
|
const { ssrRenderAttrs: _ssrRenderAttrs, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual } = require("vue/server-renderer")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
let _temp0
|
||||||
|
|
||||||
|
_push(\`<select\${
|
||||||
|
_ssrRenderAttrs(_temp0 = _mergeProps(_ctx.obj, _attrs))
|
||||||
|
}><option value="1"\${
|
||||||
|
(_ssrIncludeBooleanAttr(("value" in _temp0)
|
||||||
|
? (Array.isArray(_temp0.value))
|
||||||
|
? _ssrLooseContain(_temp0.value, "1")
|
||||||
|
: _ssrLooseEqual(_temp0.value, "1")
|
||||||
|
: false)) ? " selected" : ""
|
||||||
|
}></option></select>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await renderToString(
|
||||||
|
createApp({
|
||||||
|
data: () => ({ obj: { value: 2 } }),
|
||||||
|
template: `<div><select v-bind="obj"><option value="1">1</option><option value="2">2</option></select></div>`,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
).toMatchInlineSnapshot(
|
||||||
|
`"<div><select value="2"><option value="1">1</option><option value="2" selected>2</option></select></div>"`,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('<select> with dynamic v-bind and dynamic value bind assigns `selected` option attribute', async () => {
|
||||||
|
expect(
|
||||||
|
compile(
|
||||||
|
`<select v-bind="obj" :value="selectValue"><option value="1"></option></select>`,
|
||||||
|
).code,
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { mergeProps: _mergeProps } = require("vue")
|
||||||
|
const { ssrRenderAttrs: _ssrRenderAttrs, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual } = require("vue/server-renderer")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
let _temp0
|
||||||
|
|
||||||
|
_push(\`<select\${
|
||||||
|
_ssrRenderAttrs(_temp0 = _mergeProps(_ctx.obj, { value: _ctx.selectValue }, _attrs))
|
||||||
|
}><option value="1"\${
|
||||||
|
(_ssrIncludeBooleanAttr(("value" in _temp0)
|
||||||
|
? (Array.isArray(_temp0.value))
|
||||||
|
? _ssrLooseContain(_temp0.value, "1")
|
||||||
|
: _ssrLooseEqual(_temp0.value, "1")
|
||||||
|
: false)) ? " selected" : ""
|
||||||
|
}></option></select>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await renderToString(
|
||||||
|
createApp({
|
||||||
|
data: () => ({ obj: { value: 1 } }),
|
||||||
|
template: `<div><select v-bind="obj" :value="2"><option value="1">1</option><option value="2">2</option></select></div>`,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
).toMatchInlineSnapshot(
|
||||||
|
`"<div><select value="2"><option value="1">1</option><option value="2" selected>2</option></select></div>"`,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('<select> with dynamic v-bind and static value bind assigns `selected` option attribute', async () => {
|
||||||
|
expect(
|
||||||
|
compile(
|
||||||
|
`<select v-bind="obj" value="selectValue"><option value="1"></option></select>`,
|
||||||
|
).code,
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { mergeProps: _mergeProps } = require("vue")
|
||||||
|
const { ssrRenderAttrs: _ssrRenderAttrs, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual } = require("vue/server-renderer")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
let _temp0
|
||||||
|
|
||||||
|
_push(\`<select\${
|
||||||
|
_ssrRenderAttrs(_temp0 = _mergeProps(_ctx.obj, { value: "selectValue" }, _attrs))
|
||||||
|
}><option value="1"\${
|
||||||
|
(_ssrIncludeBooleanAttr(("value" in _temp0)
|
||||||
|
? (Array.isArray(_temp0.value))
|
||||||
|
? _ssrLooseContain(_temp0.value, "1")
|
||||||
|
: _ssrLooseEqual(_temp0.value, "1")
|
||||||
|
: false)) ? " selected" : ""
|
||||||
|
}></option></select>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await renderToString(
|
||||||
|
createApp({
|
||||||
|
data: () => ({ obj: { value: 1 } }),
|
||||||
|
template: `<div><select v-bind="obj" value="2"><option value="1">1</option><option value="2">2</option></select></div>`,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
).toMatchInlineSnapshot(
|
||||||
|
`"<div><select value="2"><option value="1">1</option><option value="2" selected>2</option></select></div>"`,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
test('multiple _ssrInterpolate at parent and child import dependency once', () => {
|
test('multiple _ssrInterpolate at parent and child import dependency once', () => {
|
||||||
expect(
|
expect(
|
||||||
compile(`<div>{{ hello }}<textarea v-bind="a"></textarea></div>`).code,
|
compile(`<div>{{ hello }}<textarea v-bind="a"></textarea></div>`).code,
|
||||||
|
|
|
@ -57,6 +57,7 @@ import {
|
||||||
type SSRTransformContext,
|
type SSRTransformContext,
|
||||||
processChildren,
|
processChildren,
|
||||||
} from '../ssrCodegenTransform'
|
} from '../ssrCodegenTransform'
|
||||||
|
import { processSelectChildren } from '../utils'
|
||||||
|
|
||||||
// for directives with children overwrite (e.g. v-html & v-text), we need to
|
// for directives with children overwrite (e.g. v-html & v-text), we need to
|
||||||
// store the raw children so that they can be added in the 2nd pass.
|
// store the raw children so that they can be added in the 2nd pass.
|
||||||
|
@ -139,6 +140,22 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} else if (node.tag === 'select') {
|
||||||
|
// <select> with dynamic v-bind. We don't know if the final props
|
||||||
|
// will contain .value, so we will have to do something special:
|
||||||
|
// assign the merged props to a temp variable, and check whether
|
||||||
|
// it contains value (if yes, mark options selected).
|
||||||
|
const tempId = `_temp${context.temps++}`
|
||||||
|
propsExp.arguments = [
|
||||||
|
createAssignmentExpression(
|
||||||
|
createSimpleExpression(tempId, false),
|
||||||
|
mergedProps,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
processSelectChildren(context, node.children, {
|
||||||
|
type: 'dynamicVBind',
|
||||||
|
tempId,
|
||||||
|
})
|
||||||
} else if (node.tag === 'input') {
|
} else if (node.tag === 'input') {
|
||||||
// <input v-bind="obj" v-model>
|
// <input v-bind="obj" v-model>
|
||||||
// we need to determine the props to render for the dynamic v-model
|
// we need to determine the props to render for the dynamic v-model
|
||||||
|
@ -223,10 +240,17 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_SLOT_MISPLACED, prop.loc),
|
createCompilerError(ErrorCodes.X_V_SLOT_MISPLACED, prop.loc),
|
||||||
)
|
)
|
||||||
} else if (isTextareaWithValue(node, prop) && prop.exp) {
|
} else if (isTagWithValueBind(node, 'textarea', prop) && prop.exp) {
|
||||||
if (!needMergeProps) {
|
if (!needMergeProps) {
|
||||||
node.children = [createInterpolation(prop.exp, prop.loc)]
|
node.children = [createInterpolation(prop.exp, prop.loc)]
|
||||||
}
|
}
|
||||||
|
} else if (isTagWithValueBind(node, 'select', prop) && prop.exp) {
|
||||||
|
if (!needMergeProps) {
|
||||||
|
processSelectChildren(context, node.children, {
|
||||||
|
type: 'dynamicValue',
|
||||||
|
value: prop.exp,
|
||||||
|
})
|
||||||
|
}
|
||||||
} else if (!needMergeProps && prop.name !== 'on') {
|
} else if (!needMergeProps && prop.name !== 'on') {
|
||||||
// Directive transforms.
|
// Directive transforms.
|
||||||
const directiveTransform = context.directiveTransforms[prop.name]
|
const directiveTransform = context.directiveTransforms[prop.name]
|
||||||
|
@ -326,6 +350,13 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
|
||||||
const name = prop.name
|
const name = prop.name
|
||||||
if (node.tag === 'textarea' && name === 'value' && prop.value) {
|
if (node.tag === 'textarea' && name === 'value' && prop.value) {
|
||||||
rawChildrenMap.set(node, escapeHtml(prop.value.content))
|
rawChildrenMap.set(node, escapeHtml(prop.value.content))
|
||||||
|
} else if (node.tag === 'select' && name === 'value' && prop.value) {
|
||||||
|
if (!needMergeProps) {
|
||||||
|
processSelectChildren(context, node.children, {
|
||||||
|
type: 'staticValue',
|
||||||
|
value: prop.value.content,
|
||||||
|
})
|
||||||
|
}
|
||||||
} else if (!needMergeProps) {
|
} else if (!needMergeProps) {
|
||||||
if (name === 'key' || name === 'ref') {
|
if (name === 'key' || name === 'ref') {
|
||||||
continue
|
continue
|
||||||
|
@ -399,12 +430,13 @@ function isTrueFalseValue(prop: DirectiveNode | AttributeNode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isTextareaWithValue(
|
function isTagWithValueBind(
|
||||||
node: PlainElementNode,
|
node: PlainElementNode,
|
||||||
|
targetTag: string,
|
||||||
prop: DirectiveNode,
|
prop: DirectiveNode,
|
||||||
): boolean {
|
): boolean {
|
||||||
return !!(
|
return !!(
|
||||||
node.tag === 'textarea' &&
|
node.tag === targetTag &&
|
||||||
prop.name === 'bind' &&
|
prop.name === 'bind' &&
|
||||||
isStaticArgOf(prop.arg, 'value')
|
isStaticArgOf(prop.arg, 'value')
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,27 +2,23 @@ import {
|
||||||
DOMErrorCodes,
|
DOMErrorCodes,
|
||||||
type DirectiveTransform,
|
type DirectiveTransform,
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
type ExpressionNode,
|
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
type PlainElementNode,
|
|
||||||
type TemplateChildNode,
|
|
||||||
createCallExpression,
|
createCallExpression,
|
||||||
createConditionalExpression,
|
createConditionalExpression,
|
||||||
createDOMCompilerError,
|
createDOMCompilerError,
|
||||||
createInterpolation,
|
createInterpolation,
|
||||||
createObjectProperty,
|
createObjectProperty,
|
||||||
createSimpleExpression,
|
|
||||||
findProp,
|
findProp,
|
||||||
hasDynamicKeyVBind,
|
hasDynamicKeyVBind,
|
||||||
transformModel,
|
transformModel,
|
||||||
} from '@vue/compiler-dom'
|
} from '@vue/compiler-dom'
|
||||||
import {
|
import {
|
||||||
SSR_INCLUDE_BOOLEAN_ATTR,
|
|
||||||
SSR_LOOSE_CONTAIN,
|
SSR_LOOSE_CONTAIN,
|
||||||
SSR_LOOSE_EQUAL,
|
SSR_LOOSE_EQUAL,
|
||||||
SSR_RENDER_DYNAMIC_MODEL,
|
SSR_RENDER_DYNAMIC_MODEL,
|
||||||
} from '../runtimeHelpers'
|
} from '../runtimeHelpers'
|
||||||
import type { DirectiveTransformResult } from 'packages/compiler-core/src/transform'
|
import type { DirectiveTransformResult } from 'packages/compiler-core/src/transform'
|
||||||
|
import { findValueBinding, processSelectChildren } from '../utils'
|
||||||
|
|
||||||
export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
|
export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
const model = dir.exp!
|
const model = dir.exp!
|
||||||
|
@ -39,48 +35,6 @@ export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const processSelectChildren = (children: TemplateChildNode[]) => {
|
|
||||||
children.forEach(child => {
|
|
||||||
if (child.type === NodeTypes.ELEMENT) {
|
|
||||||
processOption(child as PlainElementNode)
|
|
||||||
} else if (child.type === NodeTypes.FOR) {
|
|
||||||
processSelectChildren(child.children)
|
|
||||||
} else if (child.type === NodeTypes.IF) {
|
|
||||||
child.branches.forEach(b => processSelectChildren(b.children))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function processOption(plainNode: PlainElementNode) {
|
|
||||||
if (plainNode.tag === 'option') {
|
|
||||||
if (plainNode.props.findIndex(p => p.name === 'selected') === -1) {
|
|
||||||
const value = findValueBinding(plainNode)
|
|
||||||
plainNode.ssrCodegenNode!.elements.push(
|
|
||||||
createConditionalExpression(
|
|
||||||
createCallExpression(context.helper(SSR_INCLUDE_BOOLEAN_ATTR), [
|
|
||||||
createConditionalExpression(
|
|
||||||
createCallExpression(`Array.isArray`, [model]),
|
|
||||||
createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
|
|
||||||
model,
|
|
||||||
value,
|
|
||||||
]),
|
|
||||||
createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
|
|
||||||
model,
|
|
||||||
value,
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
createSimpleExpression(' selected', true),
|
|
||||||
createSimpleExpression('', true),
|
|
||||||
false /* no newline */,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else if (plainNode.tag === 'optgroup') {
|
|
||||||
processSelectChildren(plainNode.children)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.tagType === ElementTypes.ELEMENT) {
|
if (node.tagType === ElementTypes.ELEMENT) {
|
||||||
const res: DirectiveTransformResult = { props: [] }
|
const res: DirectiveTransformResult = { props: [] }
|
||||||
const defaultProps = [
|
const defaultProps = [
|
||||||
|
@ -173,7 +127,10 @@ export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
checkDuplicatedValue()
|
checkDuplicatedValue()
|
||||||
node.children = [createInterpolation(model, model.loc)]
|
node.children = [createInterpolation(model, model.loc)]
|
||||||
} else if (node.tag === 'select') {
|
} else if (node.tag === 'select') {
|
||||||
processSelectChildren(node.children)
|
processSelectChildren(context, node.children, {
|
||||||
|
type: 'dynamicValue',
|
||||||
|
value: model,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
context.onError(
|
context.onError(
|
||||||
createDOMCompilerError(
|
createDOMCompilerError(
|
||||||
|
@ -189,12 +146,3 @@ export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
return transformModel(dir, node, context)
|
return transformModel(dir, node, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function findValueBinding(node: PlainElementNode): ExpressionNode {
|
|
||||||
const valueBinding = findProp(node, 'value')
|
|
||||||
return valueBinding
|
|
||||||
? valueBinding.type === NodeTypes.DIRECTIVE
|
|
||||||
? valueBinding.exp!
|
|
||||||
: createSimpleExpression(valueBinding.value!.content, true)
|
|
||||||
: createSimpleExpression(`null`, false)
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
import {
|
||||||
|
type ExpressionNode,
|
||||||
|
NodeTypes,
|
||||||
|
type PlainElementNode,
|
||||||
|
type TemplateChildNode,
|
||||||
|
type TransformContext,
|
||||||
|
createCallExpression,
|
||||||
|
createConditionalExpression,
|
||||||
|
createSimpleExpression,
|
||||||
|
findProp,
|
||||||
|
} from '@vue/compiler-core'
|
||||||
|
import {
|
||||||
|
SSR_INCLUDE_BOOLEAN_ATTR,
|
||||||
|
SSR_LOOSE_CONTAIN,
|
||||||
|
SSR_LOOSE_EQUAL,
|
||||||
|
} from './runtimeHelpers'
|
||||||
|
|
||||||
|
export function findValueBinding(node: PlainElementNode): ExpressionNode {
|
||||||
|
const valueBinding = findProp(node, 'value')
|
||||||
|
return valueBinding
|
||||||
|
? valueBinding.type === NodeTypes.DIRECTIVE
|
||||||
|
? valueBinding.exp!
|
||||||
|
: createSimpleExpression(valueBinding.value!.content, true)
|
||||||
|
: createSimpleExpression(`null`, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SelectValue =
|
||||||
|
| {
|
||||||
|
type: 'staticValue'
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'dynamicValue'
|
||||||
|
value: ExpressionNode
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'dynamicVBind'
|
||||||
|
tempId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const processSelectChildren = (
|
||||||
|
context: TransformContext,
|
||||||
|
children: TemplateChildNode[],
|
||||||
|
selectValue: SelectValue,
|
||||||
|
): void => {
|
||||||
|
children.forEach(child => {
|
||||||
|
if (child.type === NodeTypes.ELEMENT) {
|
||||||
|
processOption(context, child as PlainElementNode, selectValue)
|
||||||
|
} else if (child.type === NodeTypes.FOR) {
|
||||||
|
processSelectChildren(context, child.children, selectValue)
|
||||||
|
} else if (child.type === NodeTypes.IF) {
|
||||||
|
child.branches.forEach(b =>
|
||||||
|
processSelectChildren(context, b.children, selectValue),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function processOption(
|
||||||
|
context: TransformContext,
|
||||||
|
plainNode: PlainElementNode,
|
||||||
|
selectValue: SelectValue,
|
||||||
|
): void {
|
||||||
|
if (plainNode.tag === 'option') {
|
||||||
|
if (plainNode.props.findIndex(p => p.name === 'selected') === -1) {
|
||||||
|
const value = findValueBinding(plainNode)
|
||||||
|
|
||||||
|
function createDynamicSelectExpression(selectValue: ExpressionNode) {
|
||||||
|
return createConditionalExpression(
|
||||||
|
createCallExpression(`Array.isArray`, [selectValue]),
|
||||||
|
createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
|
||||||
|
selectValue,
|
||||||
|
value,
|
||||||
|
]),
|
||||||
|
createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
|
||||||
|
selectValue,
|
||||||
|
value,
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
plainNode.ssrCodegenNode!.elements.push(
|
||||||
|
createConditionalExpression(
|
||||||
|
createCallExpression(context.helper(SSR_INCLUDE_BOOLEAN_ATTR), [
|
||||||
|
selectValue.type === 'staticValue'
|
||||||
|
? createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
|
||||||
|
createSimpleExpression(selectValue.value, true),
|
||||||
|
value,
|
||||||
|
])
|
||||||
|
: selectValue.type === 'dynamicValue'
|
||||||
|
? createDynamicSelectExpression(selectValue.value)
|
||||||
|
: createConditionalExpression(
|
||||||
|
createSimpleExpression(
|
||||||
|
`"value" in ${selectValue.tempId}`,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
createDynamicSelectExpression(
|
||||||
|
createSimpleExpression(
|
||||||
|
`${selectValue.tempId}.value`,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
createSimpleExpression('false', false),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
createSimpleExpression(' selected', true),
|
||||||
|
createSimpleExpression('', true),
|
||||||
|
false /* no newline */,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else if (plainNode.tag === 'optgroup') {
|
||||||
|
processSelectChildren(context, plainNode.children, selectValue)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue