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
}

View File

@ -21,7 +21,7 @@ import { warn } from './warning'
import { UnionToIntersection } from './helpers/typeUtils'
import { devtoolsComponentEmit } from './devtools'
import { AppContext } from './apiCreateApp'
import { emit as compatEmit } from './compat/eventEmitter'
import { emit as compatEmit } from './compat/instanceEventEmitter'
export type ObjectEmitsOptions = Record<
string,

View File

@ -1,9 +1,9 @@
{
"name": "@vue/compat",
"version": "3.0.11",
"description": "@vue/compat",
"description": "Vue 3 compatibility build for Vue 2",
"main": "index.js",
"module": "dist/vue.esm-bundler.js",
"module": "dist/vue.runtime.esm-bundler.js",
"types": "dist/vue.d.ts",
"unpkg": "dist/vue.global.js",
"jsdelivr": "dist/vue.global.js",

View File

@ -1,7 +1,7 @@
{
"name": "vue",
"version": "3.0.11",
"description": "vue",
"description": "The progressive JavaScript framework for buiding modern web UI.",
"main": "index.js",
"module": "dist/vue.runtime.esm-bundler.js",
"types": "dist/vue.d.ts",

View File

@ -120,13 +120,13 @@ function createConfig(format, output, plugins = []) {
let external = []
if (isGlobalBuild || isBrowserESMBuild) {
if (isGlobalBuild || isBrowserESMBuild || isCompatBuild) {
if (!packageOptions.enableNonBrowserBranches) {
// normal browser builds - non-browser only imports are tree-shaken,
// they are only listed here to suppress warnings.
external = ['source-map', '@babel/parser', 'estree-walker']
}
} else if (!isCompatBuild) {
} else {
// Node / esm-bundler builds.
// externalize all deps unless it's the compat build.
external = [