mirror of https://github.com/vuejs/core.git
refactor(runtime-vapor): record event metadata as array
This commit is contained in:
parent
7f861441d7
commit
5a0bc110d9
|
@ -1,12 +1,12 @@
|
|||
import { insert, normalizeBlock, prepend, remove } from '../src/dom/element'
|
||||
import { fragmentKey } from '../src/render'
|
||||
import { insert, normalizeBlock, prepend, remove } from '../../src/dom/element'
|
||||
import { fragmentKey } from '../../src/render'
|
||||
|
||||
const node1 = document.createTextNode('node1')
|
||||
const node2 = document.createTextNode('node2')
|
||||
const node3 = document.createTextNode('node3')
|
||||
const anchor = document.createTextNode('anchor')
|
||||
|
||||
describe('dom', () => {
|
||||
describe('element', () => {
|
||||
test('normalizeBlock', () => {
|
||||
expect(normalizeBlock([node1, node2, node3])).toEqual([node1, node2, node3])
|
||||
expect(normalizeBlock([node1, [node2, [node3]]])).toEqual([
|
|
@ -13,7 +13,7 @@ import {
|
|||
createComponentInstance,
|
||||
setCurrentInstance,
|
||||
} from '../../src/component'
|
||||
import { MetadataKind, getMetadata, recordMetadata } from '../../src/metadata'
|
||||
import { getMetadata, recordPropMetadata } from '../../src/metadata'
|
||||
|
||||
let removeComponentInstance = NOOP
|
||||
beforeEach(() => {
|
||||
|
@ -30,16 +30,16 @@ afterEach(() => {
|
|||
})
|
||||
|
||||
describe('patchProp', () => {
|
||||
describe('recordMetadata', () => {
|
||||
describe('recordPropMetadata', () => {
|
||||
test('should record prop metadata', () => {
|
||||
const node = {} as Node // the node is just a key
|
||||
let prev = recordMetadata(node, MetadataKind.prop, 'class', 'foo')
|
||||
let prev = recordPropMetadata(node, 'class', 'foo')
|
||||
expect(prev).toBeUndefined()
|
||||
prev = recordMetadata(node, MetadataKind.prop, 'class', 'bar')
|
||||
prev = recordPropMetadata(node, 'class', 'bar')
|
||||
expect(prev).toBe('foo')
|
||||
prev = recordMetadata(node, MetadataKind.prop, 'style', 'color: red')
|
||||
prev = recordPropMetadata(node, 'style', 'color: red')
|
||||
expect(prev).toBeUndefined()
|
||||
prev = recordMetadata(node, MetadataKind.prop, 'style', 'color: blue')
|
||||
prev = recordPropMetadata(node, 'style', 'color: blue')
|
||||
expect(prev).toBe('color: red')
|
||||
|
||||
expect(getMetadata(node)).toEqual([
|
||||
|
@ -51,8 +51,8 @@ describe('patchProp', () => {
|
|||
test('should have different metadata for different nodes', () => {
|
||||
const node1 = {} as Node
|
||||
const node2 = {} as Node
|
||||
recordMetadata(node1, MetadataKind.prop, 'class', 'foo')
|
||||
recordMetadata(node2, MetadataKind.prop, 'class', 'bar')
|
||||
recordPropMetadata(node1, 'class', 'foo')
|
||||
recordPropMetadata(node2, 'class', 'bar')
|
||||
expect(getMetadata(node1)).toEqual([{ class: 'foo' }, {}])
|
||||
expect(getMetadata(node2)).toEqual([{ class: 'bar' }, {}])
|
||||
})
|
|
@ -4,7 +4,7 @@ import {
|
|||
onEffectCleanup,
|
||||
onScopeDispose,
|
||||
} from '@vue/reactivity'
|
||||
import { MetadataKind, getMetadata, recordMetadata } from '../metadata'
|
||||
import { MetadataKind, getMetadata, recordEventMetadata } from '../metadata'
|
||||
import { withKeys, withModifiers } from '@vue/runtime-dom'
|
||||
|
||||
export function addEventListener(
|
||||
|
@ -29,12 +29,16 @@ export function on(
|
|||
options: AddEventListenerOptions & ModifierOptions = {},
|
||||
) {
|
||||
const handler: DelegatedHandler = eventHandler(handlerGetter, options)
|
||||
recordMetadata(el, MetadataKind.event, event, handler)
|
||||
const cleanupMetadata = recordEventMetadata(el, event, handler)
|
||||
const cleanupEvent = addEventListener(el, event, handler, options)
|
||||
|
||||
function cleanup() {
|
||||
cleanupMetadata()
|
||||
cleanupEvent()
|
||||
}
|
||||
|
||||
const cleanup = addEventListener(el, event, handler, options)
|
||||
const scope = getCurrentScope()
|
||||
const effect = getCurrentEffect()
|
||||
|
||||
if (effect && effect.scope === scope) {
|
||||
onEffectCleanup(cleanup)
|
||||
} else if (scope) {
|
||||
|
@ -55,7 +59,7 @@ export function delegate(
|
|||
) {
|
||||
const handler: DelegatedHandler = eventHandler(handlerGetter, options)
|
||||
handler.delegate = true
|
||||
recordMetadata(el, MetadataKind.event, event, handler)
|
||||
recordEventMetadata(el, event, handler)
|
||||
}
|
||||
|
||||
function eventHandler(
|
||||
|
@ -103,11 +107,15 @@ const delegatedEventHandler = (e: Event) => {
|
|||
},
|
||||
})
|
||||
while (node !== null) {
|
||||
const handler = getMetadata(node)[MetadataKind.event][e.type]
|
||||
if (handler && handler.delegate && !node.disabled) {
|
||||
const handlers = getMetadata(node)[MetadataKind.event][e.type]
|
||||
if (handlers) {
|
||||
for (const handler of handlers) {
|
||||
if (handler.delegate && !node.disabled) {
|
||||
handler(e)
|
||||
if (e.cancelBubble) return
|
||||
}
|
||||
}
|
||||
}
|
||||
node =
|
||||
node.host && node.host !== node && node.host instanceof Node
|
||||
? node.host
|
||||
|
|
|
@ -11,22 +11,17 @@ import {
|
|||
} from '@vue/shared'
|
||||
import { warn } from '../warning'
|
||||
import { setStyle } from './style'
|
||||
import { MetadataKind, getMetadata, recordMetadata } from '../metadata'
|
||||
import { MetadataKind, getMetadata, recordPropMetadata } from '../metadata'
|
||||
|
||||
export function setClass(el: Element, value: any) {
|
||||
const prev = recordMetadata(
|
||||
el,
|
||||
MetadataKind.prop,
|
||||
'class',
|
||||
(value = normalizeClass(value)),
|
||||
)
|
||||
const prev = recordPropMetadata(el, 'class', (value = normalizeClass(value)))
|
||||
if (value !== prev && (value || prev)) {
|
||||
el.className = value
|
||||
}
|
||||
}
|
||||
|
||||
export function setAttr(el: Element, key: string, value: any) {
|
||||
const oldVal = recordMetadata(el, MetadataKind.prop, key, value)
|
||||
const oldVal = recordPropMetadata(el, key, value)
|
||||
if (value !== oldVal) {
|
||||
if (value != null) {
|
||||
el.setAttribute(key, value)
|
||||
|
@ -37,7 +32,7 @@ export function setAttr(el: Element, key: string, value: any) {
|
|||
}
|
||||
|
||||
export function setDOMProp(el: any, key: string, value: any) {
|
||||
const oldVal = recordMetadata(el, MetadataKind.prop, key, value)
|
||||
const oldVal = recordPropMetadata(el, key, value)
|
||||
if (value === oldVal) return
|
||||
|
||||
if (key === 'innerHTML' || key === 'textContent') {
|
||||
|
@ -184,14 +179,14 @@ function mergeProps(...args: Data[]) {
|
|||
|
||||
export function setText(el: Node, ...values: any[]) {
|
||||
const text = values.map(v => toDisplayString(v)).join('')
|
||||
const oldVal = recordMetadata(el, MetadataKind.prop, 'textContent', text)
|
||||
const oldVal = recordPropMetadata(el, 'textContent', text)
|
||||
if (text !== oldVal) {
|
||||
el.textContent = text
|
||||
}
|
||||
}
|
||||
|
||||
export function setHtml(el: Element, value: any) {
|
||||
const oldVal = recordMetadata(el, MetadataKind.prop, 'innerHTML', value)
|
||||
const oldVal = recordPropMetadata(el, 'innerHTML', value)
|
||||
if (value !== oldVal) {
|
||||
el.innerHTML = value
|
||||
}
|
||||
|
|
|
@ -7,15 +7,10 @@ import {
|
|||
normalizeStyle,
|
||||
} from '@vue/shared'
|
||||
import { warn } from '../warning'
|
||||
import { MetadataKind, recordMetadata } from '../metadata'
|
||||
import { recordPropMetadata } from '../metadata'
|
||||
|
||||
export function setStyle(el: HTMLElement, value: any) {
|
||||
const prev = recordMetadata(
|
||||
el,
|
||||
MetadataKind.prop,
|
||||
'style',
|
||||
(value = normalizeStyle(value)),
|
||||
)
|
||||
const prev = recordPropMetadata(el, 'style', (value = normalizeStyle(value)))
|
||||
patchStyle(el, prev, value)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { Data } from '@vue/shared'
|
||||
import { type Data, remove } from '@vue/shared'
|
||||
import type { DelegatedHandler } from './dom/event'
|
||||
|
||||
export enum MetadataKind {
|
||||
|
@ -8,7 +8,7 @@ export enum MetadataKind {
|
|||
|
||||
export type ElementMetadata = [
|
||||
props: Data,
|
||||
events: Record<string, DelegatedHandler>,
|
||||
events: Record<string, DelegatedHandler[]>,
|
||||
]
|
||||
|
||||
export function getMetadata(
|
||||
|
@ -17,14 +17,16 @@ export function getMetadata(
|
|||
return el.$$metadata || (el.$$metadata = [{}, {}])
|
||||
}
|
||||
|
||||
export function recordMetadata(
|
||||
el: Node,
|
||||
kind: MetadataKind,
|
||||
key: string,
|
||||
value: any,
|
||||
): any {
|
||||
const metadata = getMetadata(el)[kind]
|
||||
export function recordPropMetadata(el: Node, key: string, value: any): any {
|
||||
const metadata = getMetadata(el)[MetadataKind.prop]
|
||||
const prev = metadata[key]
|
||||
metadata[key] = value
|
||||
return prev
|
||||
}
|
||||
|
||||
export function recordEventMetadata(el: Node, key: string, value: any) {
|
||||
const metadata = getMetadata(el)[MetadataKind.event]
|
||||
const handlers = (metadata[key] ||= [])
|
||||
handlers.push(value)
|
||||
return () => remove(handlers, value)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue