From d07fe6e4de0ad702ef9c4748a57efe1140bfbe51 Mon Sep 17 00:00:00 2001 From: "owen.huang" Date: Sun, 11 Feb 2024 10:17:59 +0800 Subject: [PATCH] fix(runtime-dom): clear prev style with string and object --- .../runtime-dom/__tests__/patchStyle.spec.ts | 15 +++++++++++ packages/runtime-dom/src/modules/style.ts | 26 +++++++++++++++---- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/packages/runtime-dom/__tests__/patchStyle.spec.ts b/packages/runtime-dom/__tests__/patchStyle.spec.ts index e7cd0984a19..4d541131195 100644 --- a/packages/runtime-dom/__tests__/patchStyle.spec.ts +++ b/packages/runtime-dom/__tests__/patchStyle.spec.ts @@ -106,6 +106,21 @@ describe(`runtime-dom: style patching`, () => { expect(el.style.getPropertyValue('--custom')).toBe('100\\;') }) + it('should clear prev style with string and object', () => { + let el = document.createElement('div') + patchProp(el, 'style', null, { color: 'red' }) + expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red;') + patchProp(el, 'style', { color: 'red' }, { fontSize: '12px' }) + expect(el.style.cssText.replace(/\s/g, '')).toBe('font-size:12px;') + + // reset el + el = document.createElement('div') + patchProp(el, 'style', null, 'color: red') + expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red;') + patchProp(el, 'style', 'color: red', { fontSize: '12px' }) + expect(el.style.cssText.replace(/\s/g, '')).toBe('font-size:12px;') + }) + it('shorthand properties', () => { const el = document.createElement('div') patchProp( diff --git a/packages/runtime-dom/src/modules/style.ts b/packages/runtime-dom/src/modules/style.ts index 9f897a6b2b0..990cead178a 100644 --- a/packages/runtime-dom/src/modules/style.ts +++ b/packages/runtime-dom/src/modules/style.ts @@ -9,12 +9,15 @@ const displayRE = /(^|;)\s*display\s*:/ export function patchStyle(el: Element, prev: Style, next: Style) { const style = (el as HTMLElement).style - const isCssString = isString(next) const currentDisplay = style.display let hasControlledDisplay = false - if (next && !isCssString) { - if (prev && !isString(prev)) { - for (const key in prev) { + + const isNextString = isString(next) + + if (next && !isNextString) { + const prevObj = isString(prev) ? parseStyleText(prev as string) : prev + if (prevObj) { + for (const key in prevObj) { if (next[key] == null) { setStyle(style, key, '') } @@ -27,7 +30,7 @@ export function patchStyle(el: Element, prev: Style, next: Style) { setStyle(style, key, next[key]) } } else { - if (isCssString) { + if (isNextString) { if (prev !== next) { // #9821 const cssVarText = (style as any)[CSS_VAR_TEXT] @@ -50,6 +53,19 @@ export function patchStyle(el: Element, prev: Style, next: Style) { } } +function parseStyleText(cssText: string) { + const res: Record = {} + const listDelimiter = /;(?![^(]*\))/g + const propertyDelimiter = /:(.+)/ + cssText.split(listDelimiter).forEach(function (item) { + if (item) { + const tmp = item.split(propertyDelimiter) + tmp.length > 1 && (res[tmp[0].trim()] = tmp[1].trim()) + } + }) + return res +} + const semicolonRE = /[^\\];\s*$/ const importantRE = /\s*!important$/