fix(compiler-ssr): handle v-model checkbox with true-value binding
This commit is contained in:
		
							parent
							
								
									48f00c0f1b
								
							
						
					
					
						commit
						fe5428db12
					
				@ -49,7 +49,7 @@ describe('ssr: v-model', () => {
 | 
			
		||||
    `)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('<input type="checkbox"', () => {
 | 
			
		||||
  test('<input type="checkbox">', () => {
 | 
			
		||||
    expect(compileWithWrapper(`<input type="checkbox" v-model="bar">`).code)
 | 
			
		||||
      .toMatchInlineSnapshot(`
 | 
			
		||||
      "const { ssrLooseContain: _ssrLooseContain, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
 | 
			
		||||
@ -81,6 +81,38 @@ describe('ssr: v-model', () => {
 | 
			
		||||
        }></div>\`)
 | 
			
		||||
      }"
 | 
			
		||||
    `)
 | 
			
		||||
 | 
			
		||||
    expect(
 | 
			
		||||
      compileWithWrapper(
 | 
			
		||||
        `<input type="checkbox" :true-value="foo" :false-value="bar" v-model="baz">`
 | 
			
		||||
      ).code
 | 
			
		||||
    ).toMatchInlineSnapshot(`
 | 
			
		||||
      "const { ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
 | 
			
		||||
 | 
			
		||||
      return function ssrRender(_ctx, _push, _parent, _attrs) {
 | 
			
		||||
        _push(\`<div\${
 | 
			
		||||
          _ssrRenderAttrs(_attrs)
 | 
			
		||||
        }><input type=\\"checkbox\\"\${
 | 
			
		||||
          (_ssrLooseEqual(_ctx.baz, _ctx.foo)) ? \\" checked\\" : \\"\\"
 | 
			
		||||
        }></div>\`)
 | 
			
		||||
      }"
 | 
			
		||||
    `)
 | 
			
		||||
 | 
			
		||||
    expect(
 | 
			
		||||
      compileWithWrapper(
 | 
			
		||||
        `<input type="checkbox" true-value="foo" false-value="bar" v-model="baz">`
 | 
			
		||||
      ).code
 | 
			
		||||
    ).toMatchInlineSnapshot(`
 | 
			
		||||
      "const { ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
 | 
			
		||||
 | 
			
		||||
      return function ssrRender(_ctx, _push, _parent, _attrs) {
 | 
			
		||||
        _push(\`<div\${
 | 
			
		||||
          _ssrRenderAttrs(_attrs)
 | 
			
		||||
        }><input type=\\"checkbox\\"\${
 | 
			
		||||
          (_ssrLooseEqual(_ctx.baz, \\"foo\\")) ? \\" checked\\" : \\"\\"
 | 
			
		||||
        }></div>\`)
 | 
			
		||||
      }"
 | 
			
		||||
    `)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('<textarea>', () => {
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,8 @@ import {
 | 
			
		||||
  isBindKey,
 | 
			
		||||
  createSequenceExpression,
 | 
			
		||||
  InterpolationNode,
 | 
			
		||||
  isStaticExp
 | 
			
		||||
  isStaticExp,
 | 
			
		||||
  AttributeNode
 | 
			
		||||
} from '@vue/compiler-dom'
 | 
			
		||||
import {
 | 
			
		||||
  escapeHtml,
 | 
			
		||||
@ -159,6 +160,10 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
 | 
			
		||||
 | 
			
		||||
    for (let i = 0; i < node.props.length; i++) {
 | 
			
		||||
      const prop = node.props[i]
 | 
			
		||||
      // ignore true-value/false-value on input
 | 
			
		||||
      if (node.tag === 'input' && isTrueFalseValue(prop)) {
 | 
			
		||||
        continue
 | 
			
		||||
      }
 | 
			
		||||
      // special cases with children override
 | 
			
		||||
      if (prop.type === NodeTypes.DIRECTIVE) {
 | 
			
		||||
        if (prop.name === 'html' && prop.exp) {
 | 
			
		||||
@ -306,6 +311,19 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isTrueFalseValue(prop: DirectiveNode | AttributeNode) {
 | 
			
		||||
  if (prop.type === NodeTypes.DIRECTIVE) {
 | 
			
		||||
    return (
 | 
			
		||||
      prop.name === 'bind' &&
 | 
			
		||||
      prop.arg &&
 | 
			
		||||
      isStaticExp(prop.arg) &&
 | 
			
		||||
      (prop.arg.content === 'true-value' || prop.arg.content === 'false-value')
 | 
			
		||||
    )
 | 
			
		||||
  } else {
 | 
			
		||||
    return prop.name === 'true-value' || prop.name === 'false-value'
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isTextareaWithValue(
 | 
			
		||||
  node: PlainElementNode,
 | 
			
		||||
  prop: DirectiveNode
 | 
			
		||||
 | 
			
		||||
@ -71,19 +71,36 @@ export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
 | 
			
		||||
              ]
 | 
			
		||||
              break
 | 
			
		||||
            case 'checkbox':
 | 
			
		||||
              res.props = [
 | 
			
		||||
                createObjectProperty(
 | 
			
		||||
                  `checked`,
 | 
			
		||||
                  createConditionalExpression(
 | 
			
		||||
                    createCallExpression(`Array.isArray`, [model]),
 | 
			
		||||
                    createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
 | 
			
		||||
              const trueValueBinding = findProp(node, 'true-value')
 | 
			
		||||
              if (trueValueBinding) {
 | 
			
		||||
                const trueValue =
 | 
			
		||||
                  trueValueBinding.type === NodeTypes.ATTRIBUTE
 | 
			
		||||
                    ? JSON.stringify(trueValueBinding.value!.content)
 | 
			
		||||
                    : trueValueBinding.exp!
 | 
			
		||||
                res.props = [
 | 
			
		||||
                  createObjectProperty(
 | 
			
		||||
                    `checked`,
 | 
			
		||||
                    createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
 | 
			
		||||
                      model,
 | 
			
		||||
                      value
 | 
			
		||||
                    ]),
 | 
			
		||||
                    model
 | 
			
		||||
                      trueValue
 | 
			
		||||
                    ])
 | 
			
		||||
                  )
 | 
			
		||||
                )
 | 
			
		||||
              ]
 | 
			
		||||
                ]
 | 
			
		||||
              } else {
 | 
			
		||||
                res.props = [
 | 
			
		||||
                  createObjectProperty(
 | 
			
		||||
                    `checked`,
 | 
			
		||||
                    createConditionalExpression(
 | 
			
		||||
                      createCallExpression(`Array.isArray`, [model]),
 | 
			
		||||
                      createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
 | 
			
		||||
                        model,
 | 
			
		||||
                        value
 | 
			
		||||
                      ]),
 | 
			
		||||
                      model
 | 
			
		||||
                    )
 | 
			
		||||
                  )
 | 
			
		||||
                ]
 | 
			
		||||
              }
 | 
			
		||||
              break
 | 
			
		||||
            case 'file':
 | 
			
		||||
              context.onError(
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user