فهرست منبع

refactor(runtime-vapor): split props & event metadata

三咲智子 Kevin Deng 2 سال پیش
والد
کامیت
23653cc447

+ 11 - 8
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: {},
       })
     })
   })

+ 1 - 1
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
 }
 

+ 14 - 19
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()

+ 11 - 6
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
   }

+ 7 - 2
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)
 }
 

+ 17 - 5
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
 }