From 23653cc447bb61199026992b6c09bbabf578529a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Fri, 23 Feb 2024 13:21:04 +0800 Subject: [PATCH] refactor(runtime-vapor): split props & event metadata --- .../__tests__/dom/patchProp.spec.ts | 19 ++++++----- .../runtime-vapor/src/directives/vModel.ts | 2 +- packages/runtime-vapor/src/dom/event.ts | 33 ++++++++----------- packages/runtime-vapor/src/dom/prop.ts | 17 ++++++---- packages/runtime-vapor/src/dom/style.ts | 9 +++-- packages/runtime-vapor/src/metadata.ts | 22 ++++++++++--- 6 files changed, 61 insertions(+), 41 deletions(-) diff --git a/packages/runtime-vapor/__tests__/dom/patchProp.spec.ts b/packages/runtime-vapor/__tests__/dom/patchProp.spec.ts index 53e2e7526..e68d008b8 100644 --- a/packages/runtime-vapor/__tests__/dom/patchProp.spec.ts +++ b/packages/runtime-vapor/__tests__/dom/patchProp.spec.ts @@ -13,7 +13,7 @@ import { createComponentInstance, setCurrentInstance, } from '../../src/component' -import { getMetadata, recordPropMetadata } from '../../src/metadata' +import { getMetadata, recordMetadata } from '../../src/metadata' let removeComponentInstance = NOOP beforeEach(() => { @@ -30,33 +30,36 @@ afterEach(() => { }) describe('patchProp', () => { - describe('recordPropMetadata', () => { + describe('recordMetadata', () => { test('should record prop metadata', () => { const node = {} as Node // the node is just a key - let prev = recordPropMetadata(node, 'class', 'foo') + let prev = recordMetadata(node, 'props', 'class', 'foo') expect(prev).toBeUndefined() - prev = recordPropMetadata(node, 'class', 'bar') + prev = recordMetadata(node, 'props', 'class', 'bar') expect(prev).toBe('foo') - prev = recordPropMetadata(node, 'style', 'color: red') + prev = recordMetadata(node, 'props', 'style', 'color: red') expect(prev).toBeUndefined() - prev = recordPropMetadata(node, 'style', 'color: blue') + prev = recordMetadata(node, 'props', 'style', 'color: blue') expect(prev).toBe('color: red') expect(getMetadata(node)).toEqual({ props: { class: 'bar', style: 'color: blue' }, + events: {}, }) }) test('should have different metadata for different nodes', () => { const node1 = {} as Node const node2 = {} as Node - recordPropMetadata(node1, 'class', 'foo') - recordPropMetadata(node2, 'class', 'bar') + recordMetadata(node1, 'props', 'class', 'foo') + recordMetadata(node2, 'props', 'class', 'bar') expect(getMetadata(node1)).toEqual({ props: { class: 'foo' }, + events: {}, }) expect(getMetadata(node2)).toEqual({ props: { class: 'bar' }, + events: {}, }) }) }) diff --git a/packages/runtime-vapor/src/directives/vModel.ts b/packages/runtime-vapor/src/directives/vModel.ts index 9327e6287..f8413ec8d 100644 --- a/packages/runtime-vapor/src/directives/vModel.ts +++ b/packages/runtime-vapor/src/directives/vModel.ts @@ -20,7 +20,7 @@ import { getMetadata } from '../metadata' type AssignerFn = (value: any) => void function getModelAssigner(el: Element): AssignerFn { const metadata = getMetadata(el) - const fn: any = metadata.props['onUpdate:modelValue'] + const fn: any = metadata.events['update:modelValue'] return isArray(fn) ? value => invokeArrayFns(fn, value) : fn } diff --git a/packages/runtime-vapor/src/dom/event.ts b/packages/runtime-vapor/src/dom/event.ts index 9f568cc99..d37fc793b 100644 --- a/packages/runtime-vapor/src/dom/event.ts +++ b/packages/runtime-vapor/src/dom/event.ts @@ -4,8 +4,7 @@ import { onEffectCleanup, onScopeDispose, } from '@vue/reactivity' -import { recordPropMetadata } from '../metadata' -import { toHandlerKey } from '@vue/shared' +import { recordMetadata } from '../metadata' import { withKeys, withModifiers } from '@vue/runtime-dom' export function addEventListener( @@ -25,24 +24,20 @@ export function on( options?: AddEventListenerOptions, { modifiers, keys }: { modifiers?: string[]; keys?: string[] } = {}, ) { - recordPropMetadata(el, toHandlerKey(event), handlerGetter) - const cleanup = addEventListener( - el, - event, - (...args: any[]) => { - let handler = handlerGetter() - if (!handler) return + const handler = (...args: any[]) => { + let handler = handlerGetter() + if (!handler) return - if (modifiers) { - handler = withModifiers(handler, modifiers) - } - if (keys) { - handler = withKeys(handler, keys) - } - handler && handler(...args) - }, - options, - ) + if (modifiers) { + handler = withModifiers(handler, modifiers) + } + if (keys) { + handler = withKeys(handler, keys) + } + handler && handler(...args) + } + recordMetadata(el, 'events', event, handler) + const cleanup = addEventListener(el, event, handler, options) const scope = getCurrentScope() const effect = getCurrentEffect() diff --git a/packages/runtime-vapor/src/dom/prop.ts b/packages/runtime-vapor/src/dom/prop.ts index 5391f1c20..e04d56555 100644 --- a/packages/runtime-vapor/src/dom/prop.ts +++ b/packages/runtime-vapor/src/dom/prop.ts @@ -11,17 +11,22 @@ import { } from '@vue/shared' import { warn } from '../warning' import { setStyle } from './style' -import { getMetadata, recordPropMetadata } from '../metadata' +import { getMetadata, recordMetadata } from '../metadata' export function setClass(el: Element, value: any) { - const prev = recordPropMetadata(el, 'class', (value = normalizeClass(value))) + const prev = recordMetadata( + el, + 'props', + 'class', + (value = normalizeClass(value)), + ) if (value !== prev && (value || prev)) { el.className = value } } export function setAttr(el: Element, key: string, value: any) { - const oldVal = recordPropMetadata(el, key, value) + const oldVal = recordMetadata(el, 'props', key, value) if (value !== oldVal) { if (value != null) { el.setAttribute(key, value) @@ -32,7 +37,7 @@ export function setAttr(el: Element, key: string, value: any) { } export function setDOMProp(el: any, key: string, value: any) { - const oldVal = recordPropMetadata(el, key, value) + const oldVal = recordMetadata(el, 'props', key, value) if (value === oldVal) return if (key === 'innerHTML' || key === 'textContent') { @@ -179,14 +184,14 @@ function mergeProps(...args: Data[]) { export function setText(el: Node, ...values: any[]) { const text = values.map(v => toDisplayString(v)).join('') - const oldVal = recordPropMetadata(el, 'textContent', text) + const oldVal = recordMetadata(el, 'props', 'textContent', text) if (text !== oldVal) { el.textContent = text } } export function setHtml(el: Element, value: any) { - const oldVal = recordPropMetadata(el, 'innerHTML', value) + const oldVal = recordMetadata(el, 'props', 'innerHTML', value) if (value !== oldVal) { el.innerHTML = value } diff --git a/packages/runtime-vapor/src/dom/style.ts b/packages/runtime-vapor/src/dom/style.ts index a6dd74fa3..7fdf6ca62 100644 --- a/packages/runtime-vapor/src/dom/style.ts +++ b/packages/runtime-vapor/src/dom/style.ts @@ -7,10 +7,15 @@ import { normalizeStyle, } from '@vue/shared' import { warn } from '../warning' -import { recordPropMetadata } from '../metadata' +import { recordMetadata } from '../metadata' export function setStyle(el: HTMLElement, value: any) { - const prev = recordPropMetadata(el, 'style', (value = normalizeStyle(value))) + const prev = recordMetadata( + el, + 'props', + 'style', + (value = normalizeStyle(value)), + ) patchStyle(el, prev, value) } diff --git a/packages/runtime-vapor/src/metadata.ts b/packages/runtime-vapor/src/metadata.ts index a8403efcb..10b2b2654 100644 --- a/packages/runtime-vapor/src/metadata.ts +++ b/packages/runtime-vapor/src/metadata.ts @@ -2,17 +2,29 @@ import type { Data } from '@vue/shared' export interface ElementMetadata { props: Data + events: Data } export function getMetadata( el: Node & { $$metadata?: ElementMetadata }, ): ElementMetadata { - return el.$$metadata || (el.$$metadata = { props: {} }) + return ( + el.$$metadata || + (el.$$metadata = { + props: {}, + events: {}, + }) + ) } -export function recordPropMetadata(el: Node, key: string, value: any): any { - const metadata = getMetadata(el) - const prev = metadata.props[key] - metadata.props[key] = value +export function recordMetadata( + el: Node, + kind: 'props' | 'events', + key: string, + value: any, +): any { + const metadata = getMetadata(el)[kind] + const prev = metadata[key] + metadata[key] = value return prev }