wip: custom directive compat
This commit is contained in:
parent
d619a770a8
commit
47b765d63a
49
packages/runtime-core/src/compat/customDirective.ts
Normal file
49
packages/runtime-core/src/compat/customDirective.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { isArray } from '@vue/shared/src'
|
||||||
|
import { ObjectDirective, DirectiveHook } from '../directives'
|
||||||
|
import { DeprecationTypes, warnDeprecation } from './deprecations'
|
||||||
|
|
||||||
|
export interface LegacyDirective {
|
||||||
|
bind?: DirectiveHook
|
||||||
|
inserted?: DirectiveHook
|
||||||
|
update?: DirectiveHook
|
||||||
|
componentUpdated?: DirectiveHook
|
||||||
|
unbind?: DirectiveHook
|
||||||
|
}
|
||||||
|
|
||||||
|
const legacyDirectiveHookMap: Partial<
|
||||||
|
Record<
|
||||||
|
keyof ObjectDirective,
|
||||||
|
keyof LegacyDirective | (keyof LegacyDirective)[]
|
||||||
|
>
|
||||||
|
> = {
|
||||||
|
beforeMount: 'bind',
|
||||||
|
mounted: 'inserted',
|
||||||
|
updated: ['update', 'componentUpdated'],
|
||||||
|
unmounted: 'unbind'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapCompatDirectiveHook(
|
||||||
|
name: keyof ObjectDirective,
|
||||||
|
dir: ObjectDirective & LegacyDirective
|
||||||
|
): DirectiveHook | DirectiveHook[] | undefined {
|
||||||
|
const mappedName = legacyDirectiveHookMap[name]
|
||||||
|
if (mappedName) {
|
||||||
|
if (isArray(mappedName)) {
|
||||||
|
const hook: DirectiveHook[] = []
|
||||||
|
mappedName.forEach(name => {
|
||||||
|
const mappedHook = dir[name]
|
||||||
|
if (mappedHook) {
|
||||||
|
__DEV__ &&
|
||||||
|
warnDeprecation(DeprecationTypes.CUSTOM_DIR, mappedName, name)
|
||||||
|
hook.push(mappedHook)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return hook.length ? hook : undefined
|
||||||
|
} else {
|
||||||
|
if (__DEV__ && dir[mappedName]) {
|
||||||
|
warnDeprecation(DeprecationTypes.CUSTOM_DIR, mappedName, name)
|
||||||
|
}
|
||||||
|
return dir[mappedName]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,9 @@ export const enum DeprecationTypes {
|
|||||||
OPTIONS_BEFORE_DESTROY,
|
OPTIONS_BEFORE_DESTROY,
|
||||||
OPTIONS_DESTROYED,
|
OPTIONS_DESTROYED,
|
||||||
|
|
||||||
PROPS_DEFAULT_THIS
|
PROPS_DEFAULT_THIS,
|
||||||
|
|
||||||
|
CUSTOM_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeprecationData = {
|
type DeprecationData = {
|
||||||
@ -157,6 +159,13 @@ const deprecations: Record<DeprecationTypes, DeprecationData> = {
|
|||||||
`props default value function no longer has access to "this". ` +
|
`props default value function no longer has access to "this". ` +
|
||||||
`(found in prop "${key}")`,
|
`(found in prop "${key}")`,
|
||||||
link: `https://v3.vuejs.org/guide/migration/props-default-this.html`
|
link: `https://v3.vuejs.org/guide/migration/props-default-this.html`
|
||||||
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.CUSTOM_DIR]: {
|
||||||
|
message: (legacyHook: string, newHook: string) =>
|
||||||
|
`Custom directive hook "${legacyHook}" has been removed. ` +
|
||||||
|
`Use "${newHook}" instead.`,
|
||||||
|
link: `https://v3.vuejs.org/guide/migration/custom-directives.html`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ import { nextTick } from '../scheduler'
|
|||||||
import { warnDeprecation, DeprecationTypes } from './deprecations'
|
import { warnDeprecation, DeprecationTypes } from './deprecations'
|
||||||
import { version } from '..'
|
import { version } from '..'
|
||||||
import { LegacyConfig } from './globalConfig'
|
import { LegacyConfig } from './globalConfig'
|
||||||
|
import { LegacyDirective } from './customDirective'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated the default `Vue` export has been removed in Vue 3. The type for
|
* @deprecated the default `Vue` export has been removed in Vue 3. The type for
|
||||||
@ -94,6 +95,12 @@ export function createCompatVue(
|
|||||||
function createCompatApp(options: ComponentOptions = {}, Ctor: any) {
|
function createCompatApp(options: ComponentOptions = {}, Ctor: any) {
|
||||||
const app = createApp(options)
|
const app = createApp(options)
|
||||||
|
|
||||||
|
// copy over asset registries and deopt flag
|
||||||
|
;['mixins', 'components', 'directives', 'deopt'].forEach(key => {
|
||||||
|
// @ts-ignore
|
||||||
|
app._context[key] = singletonApp._context[key]
|
||||||
|
})
|
||||||
|
|
||||||
// copy over global config mutations
|
// copy over global config mutations
|
||||||
isCopyingConfig = true
|
isCopyingConfig = true
|
||||||
for (const key in singletonApp.config) {
|
for (const key in singletonApp.config) {
|
||||||
@ -184,7 +191,7 @@ export function createCompatVue(
|
|||||||
return Vue
|
return Vue
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.component = ((name: string, comp: any) => {
|
Vue.component = ((name: string, comp: Component) => {
|
||||||
if (comp) {
|
if (comp) {
|
||||||
singletonApp.component(name, comp)
|
singletonApp.component(name, comp)
|
||||||
return Vue
|
return Vue
|
||||||
@ -193,9 +200,9 @@ export function createCompatVue(
|
|||||||
}
|
}
|
||||||
}) as any
|
}) as any
|
||||||
|
|
||||||
Vue.directive = ((name: string, dir: any) => {
|
Vue.directive = ((name: string, dir: Directive | LegacyDirective) => {
|
||||||
if (dir) {
|
if (dir) {
|
||||||
singletonApp.directive(name, dir)
|
singletonApp.directive(name, dir as Directive)
|
||||||
return Vue
|
return Vue
|
||||||
} else {
|
} else {
|
||||||
return singletonApp.directive(name)
|
return singletonApp.directive(name)
|
||||||
|
@ -18,6 +18,7 @@ import { ComponentInternalInstance, Data } from './component'
|
|||||||
import { currentRenderingInstance } from './componentRenderContext'
|
import { currentRenderingInstance } from './componentRenderContext'
|
||||||
import { callWithAsyncErrorHandling, ErrorCodes } from './errorHandling'
|
import { callWithAsyncErrorHandling, ErrorCodes } from './errorHandling'
|
||||||
import { ComponentPublicInstance } from './componentPublicInstance'
|
import { ComponentPublicInstance } from './componentPublicInstance'
|
||||||
|
import { mapCompatDirectiveHook } from './compat/customDirective'
|
||||||
|
|
||||||
export interface DirectiveBinding<V = any> {
|
export interface DirectiveBinding<V = any> {
|
||||||
instance: ComponentPublicInstance | null
|
instance: ComponentPublicInstance | null
|
||||||
@ -124,7 +125,10 @@ export function invokeDirectiveHook(
|
|||||||
if (oldBindings) {
|
if (oldBindings) {
|
||||||
binding.oldValue = oldBindings[i].value
|
binding.oldValue = oldBindings[i].value
|
||||||
}
|
}
|
||||||
const hook = binding.dir[name] as DirectiveHook | undefined
|
let hook = binding.dir[name] as DirectiveHook | DirectiveHook[] | undefined
|
||||||
|
if (__COMPAT__ && !hook) {
|
||||||
|
hook = mapCompatDirectiveHook(name, binding.dir)
|
||||||
|
}
|
||||||
if (hook) {
|
if (hook) {
|
||||||
callWithAsyncErrorHandling(hook, instance, ErrorCodes.DIRECTIVE_HOOK, [
|
callWithAsyncErrorHandling(hook, instance, ErrorCodes.DIRECTIVE_HOOK, [
|
||||||
vnode.el,
|
vnode.el,
|
||||||
|
Loading…
Reference in New Issue
Block a user