mirror of https://github.com/vuejs/core.git
refactor: use symbol for private properties (#8681)
This commit is contained in:
parent
02c6924bcd
commit
2ffe3d5b3e
|
@ -22,6 +22,9 @@ import { RendererElement } from '../renderer'
|
||||||
|
|
||||||
type Hook<T = () => void> = T | T[]
|
type Hook<T = () => void> = T | T[]
|
||||||
|
|
||||||
|
const leaveCbKey = Symbol('_leaveCb')
|
||||||
|
const enterCbKey = Symbol('_enterCb')
|
||||||
|
|
||||||
export interface BaseTransitionProps<HostElement = RendererElement> {
|
export interface BaseTransitionProps<HostElement = RendererElement> {
|
||||||
mode?: 'in-out' | 'out-in' | 'default'
|
mode?: 'in-out' | 'out-in' | 'default'
|
||||||
appear?: boolean
|
appear?: boolean
|
||||||
|
@ -89,8 +92,8 @@ export interface TransitionElement {
|
||||||
// in persisted mode (e.g. v-show), the same element is toggled, so the
|
// in persisted mode (e.g. v-show), the same element is toggled, so the
|
||||||
// pending enter/leave callbacks may need to be cancelled if the state is toggled
|
// pending enter/leave callbacks may need to be cancelled if the state is toggled
|
||||||
// before it finishes.
|
// before it finishes.
|
||||||
_enterCb?: PendingCallback
|
[enterCbKey]?: PendingCallback
|
||||||
_leaveCb?: PendingCallback
|
[leaveCbKey]?: PendingCallback
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useTransitionState(): TransitionState {
|
export function useTransitionState(): TransitionState {
|
||||||
|
@ -259,9 +262,9 @@ const BaseTransitionImpl: ComponentOptions = {
|
||||||
)
|
)
|
||||||
leavingVNodesCache[String(oldInnerChild.key)] = oldInnerChild
|
leavingVNodesCache[String(oldInnerChild.key)] = oldInnerChild
|
||||||
// early removal callback
|
// early removal callback
|
||||||
el._leaveCb = () => {
|
el[leaveCbKey] = () => {
|
||||||
earlyRemove()
|
earlyRemove()
|
||||||
el._leaveCb = undefined
|
el[leaveCbKey] = undefined
|
||||||
delete enterHooks.delayedLeave
|
delete enterHooks.delayedLeave
|
||||||
}
|
}
|
||||||
enterHooks.delayedLeave = delayedLeave
|
enterHooks.delayedLeave = delayedLeave
|
||||||
|
@ -366,18 +369,18 @@ export function resolveTransitionHooks(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// for same element (v-show)
|
// for same element (v-show)
|
||||||
if (el._leaveCb) {
|
if (el[leaveCbKey]) {
|
||||||
el._leaveCb(true /* cancelled */)
|
el[leaveCbKey](true /* cancelled */)
|
||||||
}
|
}
|
||||||
// for toggled element with same key (v-if)
|
// for toggled element with same key (v-if)
|
||||||
const leavingVNode = leavingVNodesCache[key]
|
const leavingVNode = leavingVNodesCache[key]
|
||||||
if (
|
if (
|
||||||
leavingVNode &&
|
leavingVNode &&
|
||||||
isSameVNodeType(vnode, leavingVNode) &&
|
isSameVNodeType(vnode, leavingVNode) &&
|
||||||
leavingVNode.el!._leaveCb
|
(leavingVNode.el as TransitionElement)[leaveCbKey]
|
||||||
) {
|
) {
|
||||||
// force early removal (not cancelled)
|
// force early removal (not cancelled)
|
||||||
leavingVNode.el!._leaveCb()
|
;(leavingVNode.el as TransitionElement)[leaveCbKey]!()
|
||||||
}
|
}
|
||||||
callHook(hook, [el])
|
callHook(hook, [el])
|
||||||
},
|
},
|
||||||
|
@ -396,7 +399,7 @@ export function resolveTransitionHooks(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let called = false
|
let called = false
|
||||||
const done = (el._enterCb = (cancelled?) => {
|
const done = (el[enterCbKey] = (cancelled?) => {
|
||||||
if (called) return
|
if (called) return
|
||||||
called = true
|
called = true
|
||||||
if (cancelled) {
|
if (cancelled) {
|
||||||
|
@ -407,7 +410,7 @@ export function resolveTransitionHooks(
|
||||||
if (hooks.delayedLeave) {
|
if (hooks.delayedLeave) {
|
||||||
hooks.delayedLeave()
|
hooks.delayedLeave()
|
||||||
}
|
}
|
||||||
el._enterCb = undefined
|
el[enterCbKey] = undefined
|
||||||
})
|
})
|
||||||
if (hook) {
|
if (hook) {
|
||||||
callAsyncHook(hook, [el, done])
|
callAsyncHook(hook, [el, done])
|
||||||
|
@ -418,15 +421,15 @@ export function resolveTransitionHooks(
|
||||||
|
|
||||||
leave(el, remove) {
|
leave(el, remove) {
|
||||||
const key = String(vnode.key)
|
const key = String(vnode.key)
|
||||||
if (el._enterCb) {
|
if (el[enterCbKey]) {
|
||||||
el._enterCb(true /* cancelled */)
|
el[enterCbKey](true /* cancelled */)
|
||||||
}
|
}
|
||||||
if (state.isUnmounting) {
|
if (state.isUnmounting) {
|
||||||
return remove()
|
return remove()
|
||||||
}
|
}
|
||||||
callHook(onBeforeLeave, [el])
|
callHook(onBeforeLeave, [el])
|
||||||
let called = false
|
let called = false
|
||||||
const done = (el._leaveCb = (cancelled?) => {
|
const done = (el[leaveCbKey] = (cancelled?) => {
|
||||||
if (called) return
|
if (called) return
|
||||||
called = true
|
called = true
|
||||||
remove()
|
remove()
|
||||||
|
@ -435,7 +438,7 @@ export function resolveTransitionHooks(
|
||||||
} else {
|
} else {
|
||||||
callHook(onAfterLeave, [el])
|
callHook(onAfterLeave, [el])
|
||||||
}
|
}
|
||||||
el._leaveCb = undefined
|
el[leaveCbKey] = undefined
|
||||||
if (leavingVNodesCache[key] === vnode) {
|
if (leavingVNodesCache[key] === vnode) {
|
||||||
delete leavingVNodesCache[key]
|
delete leavingVNodesCache[key]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { patchProp } from '../src/patchProp'
|
import { patchProp } from '../src/patchProp'
|
||||||
import { ElementWithTransition } from '../src/components/Transition'
|
import { ElementWithTransition, vtcKey } from '../src/components/Transition'
|
||||||
import { svgNS } from '../src/nodeOps'
|
import { svgNS } from '../src/nodeOps'
|
||||||
|
|
||||||
describe('runtime-dom: class patching', () => {
|
describe('runtime-dom: class patching', () => {
|
||||||
|
@ -13,12 +13,12 @@ describe('runtime-dom: class patching', () => {
|
||||||
|
|
||||||
test('transition class', () => {
|
test('transition class', () => {
|
||||||
const el = document.createElement('div') as ElementWithTransition
|
const el = document.createElement('div') as ElementWithTransition
|
||||||
el._vtc = new Set(['bar', 'baz'])
|
el[vtcKey] = new Set(['bar', 'baz'])
|
||||||
patchProp(el, 'class', null, 'foo')
|
patchProp(el, 'class', null, 'foo')
|
||||||
expect(el.className).toBe('foo bar baz')
|
expect(el.className).toBe('foo bar baz')
|
||||||
patchProp(el, 'class', null, null)
|
patchProp(el, 'class', null, null)
|
||||||
expect(el.className).toBe('bar baz')
|
expect(el.className).toBe('bar baz')
|
||||||
delete el._vtc
|
delete el[vtcKey]
|
||||||
patchProp(el, 'class', null, 'foo')
|
patchProp(el, 'class', null, 'foo')
|
||||||
expect(el.className).toBe('foo')
|
expect(el.className).toBe('foo')
|
||||||
})
|
})
|
||||||
|
|
|
@ -32,12 +32,14 @@ export interface TransitionProps extends BaseTransitionProps<Element> {
|
||||||
leaveToClass?: string
|
leaveToClass?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const vtcKey = Symbol('_vtc')
|
||||||
|
|
||||||
export interface ElementWithTransition extends HTMLElement {
|
export interface ElementWithTransition extends HTMLElement {
|
||||||
// _vtc = Vue Transition Classes.
|
// _vtc = Vue Transition Classes.
|
||||||
// Store the temporarily-added transition classes on the element
|
// Store the temporarily-added transition classes on the element
|
||||||
// so that we can avoid overwriting them if the element's class is patched
|
// so that we can avoid overwriting them if the element's class is patched
|
||||||
// during the transition.
|
// during the transition.
|
||||||
_vtc?: Set<string>
|
[vtcKey]?: Set<string>
|
||||||
}
|
}
|
||||||
|
|
||||||
// DOM Transition is a higher-order-component based on the platform-agnostic
|
// DOM Transition is a higher-order-component based on the platform-agnostic
|
||||||
|
@ -295,18 +297,18 @@ function NumberOf(val: unknown): number {
|
||||||
export function addTransitionClass(el: Element, cls: string) {
|
export function addTransitionClass(el: Element, cls: string) {
|
||||||
cls.split(/\s+/).forEach(c => c && el.classList.add(c))
|
cls.split(/\s+/).forEach(c => c && el.classList.add(c))
|
||||||
;(
|
;(
|
||||||
(el as ElementWithTransition)._vtc ||
|
(el as ElementWithTransition)[vtcKey] ||
|
||||||
((el as ElementWithTransition)._vtc = new Set())
|
((el as ElementWithTransition)[vtcKey] = new Set())
|
||||||
).add(cls)
|
).add(cls)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeTransitionClass(el: Element, cls: string) {
|
export function removeTransitionClass(el: Element, cls: string) {
|
||||||
cls.split(/\s+/).forEach(c => c && el.classList.remove(c))
|
cls.split(/\s+/).forEach(c => c && el.classList.remove(c))
|
||||||
const { _vtc } = el as ElementWithTransition
|
const _vtc = (el as ElementWithTransition)[vtcKey]
|
||||||
if (_vtc) {
|
if (_vtc) {
|
||||||
_vtc.delete(cls)
|
_vtc.delete(cls)
|
||||||
if (!_vtc!.size) {
|
if (!_vtc!.size) {
|
||||||
;(el as ElementWithTransition)._vtc = undefined
|
;(el as ElementWithTransition)[vtcKey] = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@ import {
|
||||||
getTransitionInfo,
|
getTransitionInfo,
|
||||||
resolveTransitionProps,
|
resolveTransitionProps,
|
||||||
TransitionPropsValidators,
|
TransitionPropsValidators,
|
||||||
forceReflow
|
forceReflow,
|
||||||
|
vtcKey
|
||||||
} from './Transition'
|
} from './Transition'
|
||||||
import {
|
import {
|
||||||
Fragment,
|
Fragment,
|
||||||
|
@ -29,7 +30,8 @@ import { extend } from '@vue/shared'
|
||||||
|
|
||||||
const positionMap = new WeakMap<VNode, DOMRect>()
|
const positionMap = new WeakMap<VNode, DOMRect>()
|
||||||
const newPositionMap = new WeakMap<VNode, DOMRect>()
|
const newPositionMap = new WeakMap<VNode, DOMRect>()
|
||||||
|
const moveCbKey = Symbol('_moveCb')
|
||||||
|
const enterCbKey = Symbol('_enterCb')
|
||||||
export type TransitionGroupProps = Omit<TransitionProps, 'mode'> & {
|
export type TransitionGroupProps = Omit<TransitionProps, 'mode'> & {
|
||||||
tag?: string
|
tag?: string
|
||||||
moveClass?: string
|
moveClass?: string
|
||||||
|
@ -80,13 +82,13 @@ const TransitionGroupImpl: ComponentOptions = {
|
||||||
const style = el.style
|
const style = el.style
|
||||||
addTransitionClass(el, moveClass)
|
addTransitionClass(el, moveClass)
|
||||||
style.transform = style.webkitTransform = style.transitionDuration = ''
|
style.transform = style.webkitTransform = style.transitionDuration = ''
|
||||||
const cb = ((el as any)._moveCb = (e: TransitionEvent) => {
|
const cb = ((el as any)[moveCbKey] = (e: TransitionEvent) => {
|
||||||
if (e && e.target !== el) {
|
if (e && e.target !== el) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!e || /transform$/.test(e.propertyName)) {
|
if (!e || /transform$/.test(e.propertyName)) {
|
||||||
el.removeEventListener('transitionend', cb)
|
el.removeEventListener('transitionend', cb)
|
||||||
;(el as any)._moveCb = null
|
;(el as any)[moveCbKey] = null
|
||||||
removeTransitionClass(el, moveClass)
|
removeTransitionClass(el, moveClass)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -162,11 +164,11 @@ export const TransitionGroup = TransitionGroupImpl as unknown as {
|
||||||
|
|
||||||
function callPendingCbs(c: VNode) {
|
function callPendingCbs(c: VNode) {
|
||||||
const el = c.el as any
|
const el = c.el as any
|
||||||
if (el._moveCb) {
|
if (el[moveCbKey]) {
|
||||||
el._moveCb()
|
el[moveCbKey]()
|
||||||
}
|
}
|
||||||
if (el._enterCb) {
|
if (el[enterCbKey]) {
|
||||||
el._enterCb()
|
el[enterCbKey]()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,8 +200,9 @@ function hasCSSTransform(
|
||||||
// all other transition classes applied to ensure only the move class
|
// all other transition classes applied to ensure only the move class
|
||||||
// is applied.
|
// is applied.
|
||||||
const clone = el.cloneNode() as HTMLElement
|
const clone = el.cloneNode() as HTMLElement
|
||||||
if (el._vtc) {
|
const _vtc = el[vtcKey]
|
||||||
el._vtc.forEach(cls => {
|
if (_vtc) {
|
||||||
|
_vtc.forEach(cls => {
|
||||||
cls.split(/\s+/).forEach(c => c && clone.classList.remove(c))
|
cls.split(/\s+/).forEach(c => c && clone.classList.remove(c))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,9 @@ function onCompositionEnd(e: Event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ModelDirective<T> = ObjectDirective<T & { _assign: AssignerFn }>
|
const assignKey = Symbol('_assign')
|
||||||
|
|
||||||
|
type ModelDirective<T> = ObjectDirective<T & { [assignKey]: AssignerFn }>
|
||||||
|
|
||||||
// We are exporting the v-model runtime directly as vnode hooks so that it can
|
// We are exporting the v-model runtime directly as vnode hooks so that it can
|
||||||
// be tree-shaken in case v-model is never used.
|
// be tree-shaken in case v-model is never used.
|
||||||
|
@ -44,7 +46,7 @@ export const vModelText: ModelDirective<
|
||||||
HTMLInputElement | HTMLTextAreaElement
|
HTMLInputElement | HTMLTextAreaElement
|
||||||
> = {
|
> = {
|
||||||
created(el, { modifiers: { lazy, trim, number } }, vnode) {
|
created(el, { modifiers: { lazy, trim, number } }, vnode) {
|
||||||
el._assign = getModelAssigner(vnode)
|
el[assignKey] = getModelAssigner(vnode)
|
||||||
const castToNumber =
|
const castToNumber =
|
||||||
number || (vnode.props && vnode.props.type === 'number')
|
number || (vnode.props && vnode.props.type === 'number')
|
||||||
addEventListener(el, lazy ? 'change' : 'input', e => {
|
addEventListener(el, lazy ? 'change' : 'input', e => {
|
||||||
|
@ -56,7 +58,7 @@ export const vModelText: ModelDirective<
|
||||||
if (castToNumber) {
|
if (castToNumber) {
|
||||||
domValue = looseToNumber(domValue)
|
domValue = looseToNumber(domValue)
|
||||||
}
|
}
|
||||||
el._assign(domValue)
|
el[assignKey](domValue)
|
||||||
})
|
})
|
||||||
if (trim) {
|
if (trim) {
|
||||||
addEventListener(el, 'change', () => {
|
addEventListener(el, 'change', () => {
|
||||||
|
@ -78,7 +80,7 @@ export const vModelText: ModelDirective<
|
||||||
el.value = value == null ? '' : value
|
el.value = value == null ? '' : value
|
||||||
},
|
},
|
||||||
beforeUpdate(el, { value, modifiers: { lazy, trim, number } }, vnode) {
|
beforeUpdate(el, { value, modifiers: { lazy, trim, number } }, vnode) {
|
||||||
el._assign = getModelAssigner(vnode)
|
el[assignKey] = getModelAssigner(vnode)
|
||||||
// avoid clearing unresolved text. #2302
|
// avoid clearing unresolved text. #2302
|
||||||
if ((el as any).composing) return
|
if ((el as any).composing) return
|
||||||
if (document.activeElement === el && el.type !== 'range') {
|
if (document.activeElement === el && el.type !== 'range') {
|
||||||
|
@ -106,12 +108,12 @@ export const vModelCheckbox: ModelDirective<HTMLInputElement> = {
|
||||||
// #4096 array checkboxes need to be deep traversed
|
// #4096 array checkboxes need to be deep traversed
|
||||||
deep: true,
|
deep: true,
|
||||||
created(el, _, vnode) {
|
created(el, _, vnode) {
|
||||||
el._assign = getModelAssigner(vnode)
|
el[assignKey] = getModelAssigner(vnode)
|
||||||
addEventListener(el, 'change', () => {
|
addEventListener(el, 'change', () => {
|
||||||
const modelValue = (el as any)._modelValue
|
const modelValue = (el as any)._modelValue
|
||||||
const elementValue = getValue(el)
|
const elementValue = getValue(el)
|
||||||
const checked = el.checked
|
const checked = el.checked
|
||||||
const assign = el._assign
|
const assign = el[assignKey]
|
||||||
if (isArray(modelValue)) {
|
if (isArray(modelValue)) {
|
||||||
const index = looseIndexOf(modelValue, elementValue)
|
const index = looseIndexOf(modelValue, elementValue)
|
||||||
const found = index !== -1
|
const found = index !== -1
|
||||||
|
@ -138,7 +140,7 @@ export const vModelCheckbox: ModelDirective<HTMLInputElement> = {
|
||||||
// set initial checked on mount to wait for true-value/false-value
|
// set initial checked on mount to wait for true-value/false-value
|
||||||
mounted: setChecked,
|
mounted: setChecked,
|
||||||
beforeUpdate(el, binding, vnode) {
|
beforeUpdate(el, binding, vnode) {
|
||||||
el._assign = getModelAssigner(vnode)
|
el[assignKey] = getModelAssigner(vnode)
|
||||||
setChecked(el, binding, vnode)
|
setChecked(el, binding, vnode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,13 +165,13 @@ function setChecked(
|
||||||
export const vModelRadio: ModelDirective<HTMLInputElement> = {
|
export const vModelRadio: ModelDirective<HTMLInputElement> = {
|
||||||
created(el, { value }, vnode) {
|
created(el, { value }, vnode) {
|
||||||
el.checked = looseEqual(value, vnode.props!.value)
|
el.checked = looseEqual(value, vnode.props!.value)
|
||||||
el._assign = getModelAssigner(vnode)
|
el[assignKey] = getModelAssigner(vnode)
|
||||||
addEventListener(el, 'change', () => {
|
addEventListener(el, 'change', () => {
|
||||||
el._assign(getValue(el))
|
el[assignKey](getValue(el))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
beforeUpdate(el, { value, oldValue }, vnode) {
|
beforeUpdate(el, { value, oldValue }, vnode) {
|
||||||
el._assign = getModelAssigner(vnode)
|
el[assignKey] = getModelAssigner(vnode)
|
||||||
if (value !== oldValue) {
|
if (value !== oldValue) {
|
||||||
el.checked = looseEqual(value, vnode.props!.value)
|
el.checked = looseEqual(value, vnode.props!.value)
|
||||||
}
|
}
|
||||||
|
@ -187,7 +189,7 @@ export const vModelSelect: ModelDirective<HTMLSelectElement> = {
|
||||||
.map((o: HTMLOptionElement) =>
|
.map((o: HTMLOptionElement) =>
|
||||||
number ? looseToNumber(getValue(o)) : getValue(o)
|
number ? looseToNumber(getValue(o)) : getValue(o)
|
||||||
)
|
)
|
||||||
el._assign(
|
el[assignKey](
|
||||||
el.multiple
|
el.multiple
|
||||||
? isSetModel
|
? isSetModel
|
||||||
? new Set(selectedVal)
|
? new Set(selectedVal)
|
||||||
|
@ -195,7 +197,7 @@ export const vModelSelect: ModelDirective<HTMLSelectElement> = {
|
||||||
: selectedVal[0]
|
: selectedVal[0]
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
el._assign = getModelAssigner(vnode)
|
el[assignKey] = getModelAssigner(vnode)
|
||||||
},
|
},
|
||||||
// set value in mounted & updated because <select> relies on its children
|
// set value in mounted & updated because <select> relies on its children
|
||||||
// <option>s.
|
// <option>s.
|
||||||
|
@ -203,7 +205,7 @@ export const vModelSelect: ModelDirective<HTMLSelectElement> = {
|
||||||
setSelected(el, value)
|
setSelected(el, value)
|
||||||
},
|
},
|
||||||
beforeUpdate(el, _binding, vnode) {
|
beforeUpdate(el, _binding, vnode) {
|
||||||
el._assign = getModelAssigner(vnode)
|
el[assignKey] = getModelAssigner(vnode)
|
||||||
},
|
},
|
||||||
updated(el, { value }) {
|
updated(el, { value }) {
|
||||||
setSelected(el, value)
|
setSelected(el, value)
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import { ObjectDirective } from '@vue/runtime-core'
|
import { ObjectDirective } from '@vue/runtime-core'
|
||||||
|
|
||||||
|
export const vShowOldKey = Symbol('_vod')
|
||||||
|
|
||||||
interface VShowElement extends HTMLElement {
|
interface VShowElement extends HTMLElement {
|
||||||
// _vod = vue original display
|
// _vod = vue original display
|
||||||
_vod: string
|
[vShowOldKey]: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const vShow: ObjectDirective<VShowElement> = {
|
export const vShow: ObjectDirective<VShowElement> = {
|
||||||
beforeMount(el, { value }, { transition }) {
|
beforeMount(el, { value }, { transition }) {
|
||||||
el._vod = el.style.display === 'none' ? '' : el.style.display
|
el[vShowOldKey] = el.style.display === 'none' ? '' : el.style.display
|
||||||
if (transition && value) {
|
if (transition && value) {
|
||||||
transition.beforeEnter(el)
|
transition.beforeEnter(el)
|
||||||
} else {
|
} else {
|
||||||
|
@ -41,7 +43,7 @@ export const vShow: ObjectDirective<VShowElement> = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDisplay(el: VShowElement, value: unknown): void {
|
function setDisplay(el: VShowElement, value: unknown): void {
|
||||||
el.style.display = value ? el._vod : 'none'
|
el.style.display = value ? el[vShowOldKey] : 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSR vnode transforms, only used when user includes client-oriented render
|
// SSR vnode transforms, only used when user includes client-oriented render
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ElementWithTransition } from '../components/Transition'
|
import { ElementWithTransition, vtcKey } from '../components/Transition'
|
||||||
|
|
||||||
// compiler should normalize class + :class bindings on the same element
|
// compiler should normalize class + :class bindings on the same element
|
||||||
// into a single binding ['staticClass', dynamic]
|
// into a single binding ['staticClass', dynamic]
|
||||||
|
@ -6,7 +6,7 @@ export function patchClass(el: Element, value: string | null, isSVG: boolean) {
|
||||||
// directly setting className should be faster than setAttribute in theory
|
// directly setting className should be faster than setAttribute in theory
|
||||||
// if this is an element during a transition, take the temporary transition
|
// if this is an element during a transition, take the temporary transition
|
||||||
// classes into account.
|
// classes into account.
|
||||||
const transitionClasses = (el as ElementWithTransition)._vtc
|
const transitionClasses = (el as ElementWithTransition)[vtcKey]
|
||||||
if (transitionClasses) {
|
if (transitionClasses) {
|
||||||
value = (
|
value = (
|
||||||
value ? [value, ...transitionClasses] : [...transitionClasses]
|
value ? [value, ...transitionClasses] : [...transitionClasses]
|
||||||
|
|
|
@ -30,15 +30,17 @@ export function removeEventListener(
|
||||||
el.removeEventListener(event, handler, options)
|
el.removeEventListener(event, handler, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const veiKey = Symbol('_vei')
|
||||||
|
|
||||||
export function patchEvent(
|
export function patchEvent(
|
||||||
el: Element & { _vei?: Record<string, Invoker | undefined> },
|
el: Element & { [veiKey]?: Record<string, Invoker | undefined> },
|
||||||
rawName: string,
|
rawName: string,
|
||||||
prevValue: EventValue | null,
|
prevValue: EventValue | null,
|
||||||
nextValue: EventValue | null,
|
nextValue: EventValue | null,
|
||||||
instance: ComponentInternalInstance | null = null
|
instance: ComponentInternalInstance | null = null
|
||||||
) {
|
) {
|
||||||
// vei = vue event invokers
|
// vei = vue event invokers
|
||||||
const invokers = el._vei || (el._vei = {})
|
const invokers = el[veiKey] || (el[veiKey] = {})
|
||||||
const existingInvoker = invokers[rawName]
|
const existingInvoker = invokers[rawName]
|
||||||
if (nextValue && existingInvoker) {
|
if (nextValue && existingInvoker) {
|
||||||
// patch
|
// patch
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { isString, hyphenate, capitalize, isArray } from '@vue/shared'
|
import { isString, hyphenate, capitalize, isArray } from '@vue/shared'
|
||||||
import { camelize, warn } from '@vue/runtime-core'
|
import { camelize, warn } from '@vue/runtime-core'
|
||||||
|
import { vShowOldKey } from '../directives/vShow'
|
||||||
|
|
||||||
type Style = string | Record<string, string | string[]> | null
|
type Style = string | Record<string, string | string[]> | null
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ export function patchStyle(el: Element, prev: Style, next: Style) {
|
||||||
// indicates that the `display` of the element is controlled by `v-show`,
|
// indicates that the `display` of the element is controlled by `v-show`,
|
||||||
// so we always keep the current `display` value regardless of the `style`
|
// so we always keep the current `display` value regardless of the `style`
|
||||||
// value, thus handing over control to `v-show`.
|
// value, thus handing over control to `v-show`.
|
||||||
if ('_vod' in el) {
|
if (vShowOldKey in el) {
|
||||||
style.display = currentDisplay
|
style.display = currentDisplay
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
// - runtime-core/src/renderer.ts
|
// - runtime-core/src/renderer.ts
|
||||||
// - compiler-core/src/transforms/transformElement.ts
|
// - compiler-core/src/transforms/transformElement.ts
|
||||||
|
|
||||||
|
import { vtcKey } from '../../runtime-dom/src/components/Transition'
|
||||||
import { render, h, ref, nextTick } from '../src'
|
import { render, h, ref, nextTick } from '../src'
|
||||||
|
|
||||||
describe('SVG support', () => {
|
describe('SVG support', () => {
|
||||||
|
@ -54,7 +55,7 @@ describe('SVG support', () => {
|
||||||
|
|
||||||
// set a transition class on the <div> - which is only respected on non-svg
|
// set a transition class on the <div> - which is only respected on non-svg
|
||||||
// patches
|
// patches
|
||||||
;(f2 as any)._vtc = ['baz']
|
;(f2 as any)[vtcKey] = ['baz']
|
||||||
cls.value = 'bar'
|
cls.value = 'bar'
|
||||||
await nextTick()
|
await nextTick()
|
||||||
expect(f1.getAttribute('class')).toBe('bar')
|
expect(f1.getAttribute('class')).toBe('bar')
|
||||||
|
|
Loading…
Reference in New Issue