Просмотр исходного кода

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

fix #3199
HcySunYang 5 лет назад
Родитель
Сommit
2451dd8ae6

+ 6 - 3
packages/runtime-core/src/renderer.ts

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

+ 17 - 1
packages/runtime-dom/__tests__/nodeOps.spec.ts

@@ -1,6 +1,6 @@
 import { nodeOps } from '../src/nodeOps'
 
-describe('nodeOps', () => {
+describe('runtime-dom: node-ops', () => {
   test('the _value property should be cloned', () => {
     const el = nodeOps.createElement('input') as HTMLDivElement & {
       _value: any
@@ -9,4 +9,20 @@ describe('nodeOps', () => {
     const cloned = nodeOps.cloneNode!(el) as HTMLDivElement & { _value: any }
     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)
+  })
 })

+ 10 - 3
packages/runtime-dom/src/nodeOps.ts

@@ -19,10 +19,17 @@ export const nodeOps: Omit<RendererOptions<Node, Element>, 'patchProp'> = {
     }
   },
 
-  createElement: (tag, isSVG, is): Element =>
-    isSVG
+  createElement: (tag, isSVG, is, props): Element => {
+    const el = isSVG
       ? 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),