Explorar el Código

fix(runtime-dom): handle activeElement check in Shadow DOM for v-model (#14196)

Simon Schwedes hace 4 semanas
padre
commit
959ded22ab

+ 46 - 0
packages/runtime-dom/__tests__/directives/vModel.spec.ts

@@ -375,6 +375,52 @@ describe('vModel', () => {
     expect(data.lazy).toEqual('foo')
   })
 
+  it('should preserve unresolved trimmed text while focused in nested shadow roots', async () => {
+    const model = ref('')
+    const component = defineComponent({
+      render() {
+        return withVModel(
+          h('input', {
+            'onUpdate:modelValue': (value: string) => {
+              model.value = value
+            },
+          }),
+          model.value,
+          {
+            trim: true,
+          },
+        )
+      },
+    })
+
+    document.body.appendChild(root)
+    const outerShadowRoot = root.attachShadow({ mode: 'open' })
+    const innerHost = document.createElement('div')
+    outerShadowRoot.appendChild(innerHost)
+    const innerShadowRoot = innerHost.attachShadow({ mode: 'open' })
+
+    try {
+      render(h(component), innerShadowRoot)
+
+      const input = innerShadowRoot.querySelector('input') as HTMLInputElement
+      input.focus()
+
+      expect(document.activeElement).toBe(root)
+      expect(outerShadowRoot.activeElement).toBe(innerHost)
+      expect(innerShadowRoot.activeElement).toBe(input)
+
+      input.value = '    hello, world    '
+      triggerEvent('input', input)
+      await nextTick()
+
+      expect(model.value).toEqual('hello, world')
+      expect(input.value).toEqual('    hello, world    ')
+    } finally {
+      render(null, innerShadowRoot)
+      root.remove()
+    }
+  })
+
   it('should work with range', async () => {
     const component = defineComponent({
       data() {

+ 6 - 1
packages/runtime-dom/src/directives/vModel.ts

@@ -102,7 +102,12 @@ export const vModelText: ModelDirective<
       return
     }
 
-    if (document.activeElement === el && el.type !== 'range') {
+    const rootNode = el.getRootNode()
+    if (
+      (rootNode instanceof Document || rootNode instanceof ShadowRoot) &&
+      rootNode.activeElement === el &&
+      el.type !== 'range'
+    ) {
       // #8546
       if (lazy && value === oldValue) {
         return