wip: vm.$listeners compat

This commit is contained in:
Evan You
2021-04-08 10:06:12 -04:00
parent c1e5cfe7d6
commit 960e9deaed
10 changed files with 140 additions and 10 deletions

View File

@@ -23,6 +23,7 @@ export const enum DeprecationTypes {
INSTANCE_EVENT_EMITTER = 'INSTANCE_EVENT_EMITTER',
INSTANCE_EVENT_HOOKS = 'INSTANCE_EVENT_HOOKS',
INSTANCE_CHILDREN = 'INSTANCE_CHILDREN',
INSTANCE_LISTENERS = 'INSTANCE_LISTENERS',
OPTIONS_DATA_FN = 'OPTIONS_DATA_FN',
OPTIONS_DATA_MERGE = 'OPTIONS_DATA_MERGE',
@@ -173,6 +174,14 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
link: `https://v3.vuejs.org/guide/migration/children.html`
},
[DeprecationTypes.INSTANCE_LISTENERS]: {
message:
`vm.$listeners has been removed. Parent v-on listeners are now ` +
`included in vm.$attrs and it is no longer necessary to separately use ` +
`v-on="$listeners" if you are already using v-bind="$attrs".`,
link: `https://v3.vuejs.org/guide/migration/listeners-removed.html`
},
[DeprecationTypes.OPTIONS_DATA_FN]: {
message:
`The "data" option can no longer be a plain object. ` +

View File

@@ -1,9 +1,10 @@
import { extend, NOOP } from '@vue/shared'
import { PublicPropertiesMap } from '../componentPublicInstance'
import { getInstanceChildren } from './children'
import { getCompatChildren } from './instanceChildren'
import { assertCompatEnabled } from './compatConfig'
import { DeprecationTypes } from './deprecations'
import { off, on, once } from './eventEmitter'
import { off, on, once } from './instanceEventEmitter'
import { getCompatListeners } from './instanceListeners'
export function installCompatInstanceProperties(map: PublicPropertiesMap) {
const set = (target: any, key: any, val: any) => {
@@ -36,6 +37,7 @@ export function installCompatInstanceProperties(map: PublicPropertiesMap) {
$on: i => on.bind(null, i),
$once: i => once.bind(null, i),
$off: i => off.bind(null, i),
$children: getInstanceChildren
$children: getCompatChildren,
$listeners: getCompatListeners
} as PublicPropertiesMap)
}

View File

@@ -5,7 +5,7 @@ import { VNode } from '../vnode'
import { assertCompatEnabled } from './compatConfig'
import { DeprecationTypes } from './deprecations'
export function getInstanceChildren(
export function getCompatChildren(
instance: ComponentInternalInstance
): ComponentPublicInstance[] {
assertCompatEnabled(DeprecationTypes.INSTANCE_CHILDREN)

View File

@@ -0,0 +1,20 @@
import { isOn } from '@vue/shared'
import { ComponentInternalInstance } from '../component'
import { assertCompatEnabled } from './compatConfig'
import { DeprecationTypes } from './deprecations'
export function getCompatListeners(instance: ComponentInternalInstance) {
assertCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS)
const listeners: Record<string, Function | Function[]> = {}
const rawProps = instance.vnode.props
if (!rawProps) {
return listeners
}
for (const key in rawProps) {
if (isOn(key)) {
listeners[key[2].toLowerCase() + key.slice(3)] = rawProps[key]
}
}
return listeners
}

View File

@@ -0,0 +1,99 @@
import { isArray, isObject } from '@vue/shared'
import { Component, Data } from '../component'
import {
createVNode,
isVNode,
VNode,
VNodeArrayChildren,
VNodeProps
} from '../vnode'
interface LegacyVNodeProps {
key?: string | number
ref?: string
refInFor?: boolean
staticClass?: string
class?: unknown
staticStyle?: Record<string, unknown>
style?: Record<string, unknown>
attrs?: Record<string, unknown>
domProps?: Record<string, unknown>
on?: Record<string, Function | Function[]>
nativeOn?: Record<string, Function | Function[]>
directives?: LegacyVNodeDirective[]
slot?: string
scopedSlots?: Record<string, Function>
}
interface LegacyVNodeDirective {
name: string
value: unknown
arg?: string
modifiers?: Record<string, boolean>
}
type LegacyVNodeChildren =
| string
| number
| boolean
| VNode
| VNodeArrayChildren
export function h(
type: string | Component,
children?: LegacyVNodeChildren
): VNode
export function h(
type: string | Component,
props?: LegacyVNodeProps,
children?: LegacyVNodeChildren
): VNode
export function h(type: any, propsOrChildren?: any, children?: any): VNode {
const l = arguments.length
if (l === 2) {
if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {
// single vnode without props
if (isVNode(propsOrChildren)) {
return convertLegacySlots(createVNode(type, null, [propsOrChildren]))
}
// props without children
return convertLegacyDirectives(
createVNode(type, convertLegacyProps(propsOrChildren)),
propsOrChildren
)
} else {
// omit props
return convertLegacySlots(createVNode(type, null, propsOrChildren))
}
} else {
if (l > 3) {
children = Array.prototype.slice.call(arguments, 2)
} else if (l === 3 && isVNode(children)) {
children = [children]
}
return convertLegacySlots(
convertLegacyDirectives(
createVNode(type, convertLegacyProps(propsOrChildren), children),
propsOrChildren
)
)
}
}
function convertLegacyProps(props: LegacyVNodeProps): Data & VNodeProps {
// TODO
return {}
}
function convertLegacyDirectives(vnode: VNode, props: LegacyVNodeProps): VNode {
// TODO
return vnode
}
function convertLegacySlots(vnode: VNode): VNode {
// TODO
return vnode
}