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

fix(runtime-dom): preserve textarea resize dimensions (#14747)

close #14741
edison 1 день назад
Родитель
Сommit
11fb2fd4a2

+ 19 - 0
packages/runtime-dom/__tests__/patchStyle.spec.ts

@@ -29,6 +29,25 @@ describe(`runtime-dom: style patching`, () => {
     expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red;')
   })
 
+  it('should preserve textarea resize dimensions while reapplying unrelated unchanged object styles', () => {
+    const el = document.createElement('textarea')
+    const value = {
+      width: '200px',
+      height: '100px',
+      display: 'none',
+    }
+
+    patchProp(el, 'style', null, value)
+    el.style.width = '320px'
+    el.style.height = '160px'
+    el.style.display = 'block'
+
+    patchProp(el, 'style', value, value)
+    expect(el.style.width).toBe('320px')
+    expect(el.style.height).toBe('160px')
+    expect(el.style.display).toBe('none')
+  })
+
   it('camelCase', () => {
     const el = document.createElement('div')
     patchProp(el, 'style', {}, { marginRight: '10px' })

+ 34 - 1
packages/runtime-dom/src/modules/style.ts

@@ -36,7 +36,21 @@ export function patchStyle(el: Element, prev: Style, next: Style): void {
       if (key === 'display') {
         hasControlledDisplay = true
       }
-      setStyle(style, key, next[key])
+      const value = next[key]
+      if (value != null) {
+        if (
+          !shouldPreserveTextareaResizeStyle(
+            el,
+            key,
+            !isString(prev) && prev ? prev[key] : undefined,
+            value,
+          )
+        ) {
+          setStyle(style, key, value)
+        }
+      } else {
+        setStyle(style, key, '')
+      }
     }
   } else {
     if (isCssString) {
@@ -123,3 +137,22 @@ function autoPrefix(style: CSSStyleDeclaration, rawName: string): string {
   }
   return rawName
 }
+
+/**
+ * Browsers update textarea width/height directly during native resize.
+ * Only special-case this common textarea path for now; other resize scenarios
+ * still follow normal vnode style patching.
+ */
+function shouldPreserveTextareaResizeStyle(
+  el: Element,
+  key: string,
+  prev: string | string[] | undefined,
+  next: string | string[],
+): boolean {
+  return (
+    el.tagName === 'TEXTAREA' &&
+    (key === 'width' || key === 'height') &&
+    isString(next) &&
+    prev === next
+  )
+}