fix(runtime-core): the select tag's multiple prop should be set before the children mounting (#3202)

fix #3199
This commit is contained in:
HcySunYang 2021-03-26 04:49:34 +08:00 committed by GitHub
parent 084e932e85
commit 2451dd8ae6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 7 deletions

View File

@ -11,7 +11,8 @@ import {
Static, Static,
VNodeNormalizedRef, VNodeNormalizedRef,
VNodeHook, VNodeHook,
VNodeNormalizedRefAtom VNodeNormalizedRefAtom,
VNodeProps
} from './vnode' } from './vnode'
import { import {
ComponentInternalInstance, ComponentInternalInstance,
@ -114,7 +115,8 @@ export interface RendererOptions<
createElement( createElement(
type: string, type: string,
isSVG?: boolean, isSVG?: boolean,
isCustomizedBuiltIn?: string isCustomizedBuiltIn?: string,
vnodeProps?: (VNodeProps & { [key: string]: any }) | null
): HostElement ): HostElement
createText(text: string): HostNode createText(text: string): HostNode
createComment(text: string): HostNode createComment(text: string): HostNode
@ -738,7 +740,8 @@ function baseCreateRenderer(
el = vnode.el = hostCreateElement( el = vnode.el = hostCreateElement(
vnode.type as string, vnode.type as string,
isSVG, isSVG,
props && props.is props && props.is,
props
) )
// mount children first, since some props may rely on child content // mount children first, since some props may rely on child content

View File

@ -1,6 +1,6 @@
import { nodeOps } from '../src/nodeOps' import { nodeOps } from '../src/nodeOps'
describe('nodeOps', () => { describe('runtime-dom: node-ops', () => {
test('the _value property should be cloned', () => { test('the _value property should be cloned', () => {
const el = nodeOps.createElement('input') as HTMLDivElement & { const el = nodeOps.createElement('input') as HTMLDivElement & {
_value: any _value: any
@ -9,4 +9,20 @@ describe('nodeOps', () => {
const cloned = nodeOps.cloneNode!(el) as HTMLDivElement & { _value: any } const cloned = nodeOps.cloneNode!(el) as HTMLDivElement & { _value: any }
expect(cloned._value).toBe(1) expect(cloned._value).toBe(1)
}) })
test("the <select>'s multiple attr should be set in createElement", () => {
const el = nodeOps.createElement('select', false, undefined, {
multiple: ''
}) as HTMLSelectElement
const option1 = nodeOps.createElement('option') as HTMLOptionElement
const option2 = nodeOps.createElement('option') as HTMLOptionElement
option1.selected = true
option2.selected = true
nodeOps.insert(option1, el)
nodeOps.insert(option2, el)
expect(el.multiple).toBe(true)
expect(option1.selected).toBe(true)
expect(option2.selected).toBe(true)
})
}) })

View File

@ -19,10 +19,17 @@ export const nodeOps: Omit<RendererOptions<Node, Element>, 'patchProp'> = {
} }
}, },
createElement: (tag, isSVG, is): Element => createElement: (tag, isSVG, is, props): Element => {
isSVG const el = isSVG
? doc.createElementNS(svgNS, tag) ? doc.createElementNS(svgNS, tag)
: doc.createElement(tag, is ? { is } : undefined), : doc.createElement(tag, is ? { is } : undefined)
if (tag === 'select' && props && props.multiple != null) {
;(el as HTMLSelectElement).setAttribute('multiple', props.multiple)
}
return el
},
createText: text => doc.createTextNode(text), createText: text => doc.createTextNode(text),