wip: progress
This commit is contained in:
parent
40e3dd28e1
commit
53b8127a9c
@ -15,8 +15,7 @@ import { RootHydrateFunction } from './hydration'
|
|||||||
import { devtoolsInitApp, devtoolsUnmountApp } from './devtools'
|
import { devtoolsInitApp, devtoolsUnmountApp } from './devtools'
|
||||||
import { isFunction, NO, isObject } from '@vue/shared'
|
import { isFunction, NO, isObject } from '@vue/shared'
|
||||||
import { version } from '.'
|
import { version } from '.'
|
||||||
import { installCompatMount } from './compat/globalMount'
|
import { installCompatMount, installLegacyConfigTraps } from './compat/global'
|
||||||
import { installLegacyConfigTraps } from './compat/globalConfig'
|
|
||||||
|
|
||||||
export interface App<HostElement = any> {
|
export interface App<HostElement = any> {
|
||||||
version: string
|
version: string
|
||||||
@ -307,7 +306,7 @@ export function createAppAPI<HostElement>(
|
|||||||
|
|
||||||
if (__COMPAT__) {
|
if (__COMPAT__) {
|
||||||
installCompatMount(app, context, render, hydrate)
|
installCompatMount(app, context, render, hydrate)
|
||||||
installLegacyConfigTraps(app.config)
|
if (__DEV__) installLegacyConfigTraps(app.config)
|
||||||
}
|
}
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
@ -1,15 +1,22 @@
|
|||||||
import { isRuntimeOnly } from '../component'
|
import { isRuntimeOnly } from '../component'
|
||||||
|
|
||||||
export const enum DeprecationTypes {
|
export const enum DeprecationTypes {
|
||||||
DOM_TEMPLATE_MOUNT,
|
|
||||||
$MOUNT,
|
|
||||||
$DESTROY,
|
|
||||||
|
|
||||||
CONFIG_SILENT,
|
CONFIG_SILENT,
|
||||||
CONFIG_DEVTOOLS,
|
CONFIG_DEVTOOLS,
|
||||||
CONFIG_KEY_CODES,
|
CONFIG_KEY_CODES,
|
||||||
CONFIG_PRODUCTION_TIP,
|
CONFIG_PRODUCTION_TIP,
|
||||||
CONFIG_IGNORED_ELEMENTS
|
CONFIG_IGNORED_ELEMENTS,
|
||||||
|
|
||||||
|
GLOBAL_PROTOTYPE,
|
||||||
|
GLOBAL_SET,
|
||||||
|
GLOBAL_DELETE,
|
||||||
|
GLOBAL_OBSERVABLE,
|
||||||
|
GLOBAL_DOM_TEMPLATE_MOUNT,
|
||||||
|
|
||||||
|
INSTANCE_SET,
|
||||||
|
INSTANCE_DELETE,
|
||||||
|
INSTANCE_MOUNT,
|
||||||
|
INSTANCE_DESTROY
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeprecationData = {
|
type DeprecationData = {
|
||||||
@ -18,26 +25,6 @@ type DeprecationData = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const deprecations: Record<DeprecationTypes, DeprecationData> = {
|
const deprecations: Record<DeprecationTypes, DeprecationData> = {
|
||||||
[DeprecationTypes.DOM_TEMPLATE_MOUNT]: {
|
|
||||||
message:
|
|
||||||
`Vue detected directives on the mount container. ` +
|
|
||||||
`In Vue 3, the container is no longer considered part of the template ` +
|
|
||||||
`and will not be processed/replaced.`,
|
|
||||||
link: `https://v3.vuejs.org/guide/migration/mount-changes.html`
|
|
||||||
},
|
|
||||||
|
|
||||||
[DeprecationTypes.$MOUNT]: {
|
|
||||||
message:
|
|
||||||
`vm.$mount() has been removed. ` +
|
|
||||||
`Use createApp(RootComponent).mount() instead.`,
|
|
||||||
link: `https://v3.vuejs.org/guide/migration/global-api.html#mounting-app-instance`
|
|
||||||
},
|
|
||||||
|
|
||||||
[DeprecationTypes.$DESTROY]: {
|
|
||||||
message: `vm.$destroy() has been removed. Use app.unmount() instead.`,
|
|
||||||
link: `https://v3.vuejs.org/api/application-api.html#unmount`
|
|
||||||
},
|
|
||||||
|
|
||||||
[DeprecationTypes.CONFIG_SILENT]: {
|
[DeprecationTypes.CONFIG_SILENT]: {
|
||||||
message:
|
message:
|
||||||
`config.silent has been removed because it is not good practice to ` +
|
`config.silent has been removed because it is not good practice to ` +
|
||||||
@ -75,6 +62,64 @@ const deprecations: Record<DeprecationTypes, DeprecationData> = {
|
|||||||
return msg
|
return msg
|
||||||
},
|
},
|
||||||
link: `https://v3.vuejs.org/guide/migration/global-api.html#config-ignoredelements-is-now-config-iscustomelement`
|
link: `https://v3.vuejs.org/guide/migration/global-api.html#config-ignoredelements-is-now-config-iscustomelement`
|
||||||
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.GLOBAL_PROTOTYPE]: {
|
||||||
|
message:
|
||||||
|
`Vue.prototype is no longer available in Vue 3. ` +
|
||||||
|
`Use config.globalProperties instead.`,
|
||||||
|
link: `https://v3.vuejs.org/guide/migration/global-api.html#vue-prototype-replaced-by-config-globalproperties`
|
||||||
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.GLOBAL_SET]: {
|
||||||
|
message:
|
||||||
|
`Vue.set() has been removed as it is no longer needed in Vue 3. ` +
|
||||||
|
`Simply use native JavaScript mutations.`
|
||||||
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.GLOBAL_DELETE]: {
|
||||||
|
message:
|
||||||
|
`Vue.delete() has been removed as it is no longer needed in Vue 3. ` +
|
||||||
|
`Simply use native JavaScript mutations.`
|
||||||
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.GLOBAL_OBSERVABLE]: {
|
||||||
|
message:
|
||||||
|
`Vue.observable() has been removed. ` +
|
||||||
|
`Use \`import { reactive } from "vue"\` from Composition API instead.`,
|
||||||
|
link: `https://v3.vuejs.org/api/basic-reactivity.html`
|
||||||
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.GLOBAL_DOM_TEMPLATE_MOUNT]: {
|
||||||
|
message:
|
||||||
|
`Vue detected directives on the mount container. ` +
|
||||||
|
`In Vue 3, the container is no longer considered part of the template ` +
|
||||||
|
`and will not be processed/replaced.`,
|
||||||
|
link: `https://v3.vuejs.org/guide/migration/mount-changes.html`
|
||||||
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.INSTANCE_SET]: {
|
||||||
|
message:
|
||||||
|
`vm.$set() has been removed as it is no longer needed in Vue 3. ` +
|
||||||
|
`Simply use native JavaScript mutations.`
|
||||||
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.INSTANCE_DELETE]: {
|
||||||
|
message:
|
||||||
|
`vm.$delete() has been removed as it is no longer needed in Vue 3. ` +
|
||||||
|
`Simply use native JavaScript mutations.`
|
||||||
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.INSTANCE_MOUNT]: {
|
||||||
|
message:
|
||||||
|
`The global app boostrapping API has changed: vm.$mount() and the "el" ` +
|
||||||
|
`option have been removed. Use createApp(RootComponent).mount() instead.`,
|
||||||
|
link: `https://v3.vuejs.org/guide/migration/global-api.html#mounting-app-instance`
|
||||||
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.INSTANCE_DESTROY]: {
|
||||||
|
message: `vm.$destroy() has been removed. Use app.unmount() instead.`,
|
||||||
|
link: `https://v3.vuejs.org/api/application-api.html#unmount`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,32 @@
|
|||||||
import { reactive } from '@vue/reactivity'
|
import { reactive } from '@vue/reactivity'
|
||||||
import { extend } from '@vue/shared'
|
import { isFunction } from '@vue/shared'
|
||||||
import { createApp } from '../../../runtime-dom/src'
|
import { warn } from '../warning'
|
||||||
import { App, AppConfig, Plugin } from '../apiCreateApp'
|
import { cloneVNode, createVNode } from '../vnode'
|
||||||
|
import { RootRenderFunction } from '../renderer'
|
||||||
|
import { RootHydrateFunction } from '../hydration'
|
||||||
|
import {
|
||||||
|
App,
|
||||||
|
AppConfig,
|
||||||
|
AppContext,
|
||||||
|
CreateAppFunction,
|
||||||
|
Plugin
|
||||||
|
} from '../apiCreateApp'
|
||||||
import { defineComponent } from '../apiDefineComponent'
|
import { defineComponent } from '../apiDefineComponent'
|
||||||
import { Component, ComponentOptions, isRuntimeOnly } from '../component'
|
import {
|
||||||
|
Component,
|
||||||
|
ComponentOptions,
|
||||||
|
createComponentInstance,
|
||||||
|
finishComponentSetup,
|
||||||
|
isRuntimeOnly,
|
||||||
|
setupComponent
|
||||||
|
} from '../component'
|
||||||
import { RenderFunction } from '../componentOptions'
|
import { RenderFunction } from '../componentOptions'
|
||||||
import { ComponentPublicInstance } from '../componentPublicInstance'
|
import { ComponentPublicInstance } from '../componentPublicInstance'
|
||||||
|
import { devtoolsInitApp } from '../devtools'
|
||||||
import { Directive } from '../directives'
|
import { Directive } from '../directives'
|
||||||
import { nextTick } from '../scheduler'
|
import { nextTick } from '../scheduler'
|
||||||
|
import { warnDeprecation, DeprecationTypes } from './deprecations'
|
||||||
|
import { version } from '..'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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
|
||||||
@ -21,7 +40,7 @@ export type CompatVue = Pick<App, 'version' | 'component' | 'directive'> & {
|
|||||||
new (options?: ComponentOptions): ComponentPublicInstance
|
new (options?: ComponentOptions): ComponentPublicInstance
|
||||||
|
|
||||||
version: string
|
version: string
|
||||||
config: AppConfig
|
config: AppConfig & LegacyConfig
|
||||||
|
|
||||||
extend: typeof defineComponent
|
extend: typeof defineComponent
|
||||||
nextTick: typeof nextTick
|
nextTick: typeof nextTick
|
||||||
@ -54,10 +73,40 @@ export type CompatVue = Pick<App, 'version' | 'component' | 'directive'> & {
|
|||||||
filter(name: string, arg: any): null
|
filter(name: string, arg: any): null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// legacy config warnings
|
||||||
|
export type LegacyConfig = {
|
||||||
|
/**
|
||||||
|
* @deprecated `config.silent` option has been removed
|
||||||
|
*/
|
||||||
|
silent?: boolean
|
||||||
|
/**
|
||||||
|
* @deprecated use __VUE_PROD_DEVTOOLS__ compile-time feature flag instead
|
||||||
|
* https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags
|
||||||
|
*/
|
||||||
|
devtools?: boolean
|
||||||
|
/**
|
||||||
|
* @deprecated use `config.isCustomElement` instead
|
||||||
|
* https://v3.vuejs.org/guide/migration/global-api.html#config-ignoredelements-is-now-config-iscustomelement
|
||||||
|
*/
|
||||||
|
ignoredElements?: (string | RegExp)[]
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* https://v3.vuejs.org/guide/migration/keycode-modifiers.html
|
||||||
|
*/
|
||||||
|
keyCodes?: Record<string, number | number[]>
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* https://v3.vuejs.org/guide/migration/global-api.html#config-productiontip-removed
|
||||||
|
*/
|
||||||
|
productionTip?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export let isCopyingConfig = false
|
export let isCopyingConfig = false
|
||||||
|
|
||||||
// Legacy global Vue constructor
|
// Legacy global Vue constructor
|
||||||
export function createCompatVue(): CompatVue {
|
export function createCompatVue(
|
||||||
|
createApp: CreateAppFunction<Element>
|
||||||
|
): CompatVue {
|
||||||
if (!__COMPAT__) {
|
if (!__COMPAT__) {
|
||||||
// @ts-ignore this function will never be called in non-compat mode
|
// @ts-ignore this function will never be called in non-compat mode
|
||||||
return
|
return
|
||||||
@ -86,9 +135,16 @@ export function createCompatVue(): CompatVue {
|
|||||||
isCopyingConfig = false
|
isCopyingConfig = false
|
||||||
|
|
||||||
// copy prototype augmentations as config.globalProperties
|
// copy prototype augmentations as config.globalProperties
|
||||||
|
let hasPrototypeAugmentations = false
|
||||||
for (const key in Ctor.prototype) {
|
for (const key in Ctor.prototype) {
|
||||||
|
if (key !== 'constructor') {
|
||||||
|
hasPrototypeAugmentations = true
|
||||||
|
}
|
||||||
app.config.globalProperties[key] = Ctor.prototype[key]
|
app.config.globalProperties[key] = Ctor.prototype[key]
|
||||||
}
|
}
|
||||||
|
if (hasPrototypeAugmentations) {
|
||||||
|
__DEV__ && warnDeprecation(DeprecationTypes.GLOBAL_PROTOTYPE)
|
||||||
|
}
|
||||||
|
|
||||||
const vm = app._createRoot!(options)
|
const vm = app._createRoot!(options)
|
||||||
if (options.el) {
|
if (options.el) {
|
||||||
@ -124,15 +180,21 @@ export function createCompatVue(): CompatVue {
|
|||||||
Vue.nextTick = nextTick
|
Vue.nextTick = nextTick
|
||||||
|
|
||||||
Vue.set = (target, key, value) => {
|
Vue.set = (target, key, value) => {
|
||||||
// TODO deprecation warnings
|
__DEV__ && warnDeprecation(DeprecationTypes.GLOBAL_SET)
|
||||||
target[key] = value
|
target[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.delete = (target, key) => {
|
Vue.delete = (target, key) => {
|
||||||
// TODO deprecation warnings
|
__DEV__ && warnDeprecation(DeprecationTypes.GLOBAL_DELETE)
|
||||||
delete target[key]
|
delete target[key]
|
||||||
}
|
}
|
||||||
// TODO wrap with deprecation warning
|
|
||||||
Vue.observable = reactive
|
Vue.observable = __DEV__
|
||||||
|
? (target: any) => {
|
||||||
|
warnDeprecation(DeprecationTypes.GLOBAL_OBSERVABLE)
|
||||||
|
return reactive(target)
|
||||||
|
}
|
||||||
|
: reactive
|
||||||
|
|
||||||
Vue.use = (p, ...options) => {
|
Vue.use = (p, ...options) => {
|
||||||
singletonApp.use(p, ...options)
|
singletonApp.use(p, ...options)
|
||||||
@ -169,3 +231,156 @@ export function createCompatVue(): CompatVue {
|
|||||||
|
|
||||||
return Vue
|
return Vue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function installCompatMount(
|
||||||
|
app: App,
|
||||||
|
context: AppContext,
|
||||||
|
render: RootRenderFunction,
|
||||||
|
hydrate?: RootHydrateFunction
|
||||||
|
) {
|
||||||
|
let isMounted = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vue 2 supports the behavior of creating a component instance but not
|
||||||
|
* mounting it, which is no longer possible in Vue 3 - this internal
|
||||||
|
* function simulates that behavior.
|
||||||
|
*/
|
||||||
|
app._createRoot = options => {
|
||||||
|
const component = app._component
|
||||||
|
const vnode = createVNode(component, options.propsData || null)
|
||||||
|
vnode.appContext = context
|
||||||
|
|
||||||
|
const hasNoRender =
|
||||||
|
!isFunction(component) && !component.render && !component.template
|
||||||
|
const emptyRender = () => {}
|
||||||
|
|
||||||
|
// create root instance
|
||||||
|
const instance = createComponentInstance(vnode, null, null)
|
||||||
|
// suppress "missing render fn" warning since it can't be determined
|
||||||
|
// until $mount is called
|
||||||
|
if (hasNoRender) {
|
||||||
|
instance.render = emptyRender
|
||||||
|
}
|
||||||
|
setupComponent(instance, __NODE_JS__)
|
||||||
|
vnode.component = instance
|
||||||
|
|
||||||
|
// $mount & $destroy
|
||||||
|
// these are defined on ctx and picked up by the $mount/$destroy
|
||||||
|
// public property getters on the instance proxy.
|
||||||
|
// Note: the following assumes DOM environment since the compat build
|
||||||
|
// only targets web. It essentially includes logic for app.mount from
|
||||||
|
// both runtime-core AND runtime-dom.
|
||||||
|
instance.ctx._compat_mount = (selectorOrEl: string | Element) => {
|
||||||
|
if (isMounted) {
|
||||||
|
__DEV__ && warn(`Root instance is already mounted.`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let container: Element
|
||||||
|
if (typeof selectorOrEl === 'string') {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
const result = document.querySelector(selectorOrEl)
|
||||||
|
if (!result) {
|
||||||
|
__DEV__ &&
|
||||||
|
warn(
|
||||||
|
`Failed to mount root instance: selector "${selectorOrEl}" returned null.`
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
container = result
|
||||||
|
} else {
|
||||||
|
if (!selectorOrEl) {
|
||||||
|
__DEV__ &&
|
||||||
|
warn(
|
||||||
|
`Failed to mount root instance: invalid mount target ${selectorOrEl}.`
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
container = selectorOrEl
|
||||||
|
}
|
||||||
|
|
||||||
|
const isSVG = container instanceof SVGElement
|
||||||
|
|
||||||
|
// HMR root reload
|
||||||
|
if (__DEV__) {
|
||||||
|
context.reload = () => {
|
||||||
|
const cloned = cloneVNode(vnode)
|
||||||
|
// compat mode will use instance if not reset to null
|
||||||
|
cloned.component = null
|
||||||
|
render(cloned, container, isSVG)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve in-DOM template if component did not provide render
|
||||||
|
// and no setup/mixin render functions are provided (by checking
|
||||||
|
// that the instance is still using the placeholder render fn)
|
||||||
|
if (hasNoRender && instance.render === emptyRender) {
|
||||||
|
// root directives check
|
||||||
|
if (__DEV__) {
|
||||||
|
for (let i = 0; i < container.attributes.length; i++) {
|
||||||
|
const attr = container.attributes[i]
|
||||||
|
if (attr.name !== 'v-cloak' && /^(v-|:|@)/.test(attr.name)) {
|
||||||
|
warnDeprecation(DeprecationTypes.GLOBAL_DOM_TEMPLATE_MOUNT)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
instance.render = null
|
||||||
|
;(component as ComponentOptions).template = container.innerHTML
|
||||||
|
finishComponentSetup(instance, __NODE_JS__, true /* skip options */)
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear content before mounting
|
||||||
|
container.innerHTML = ''
|
||||||
|
|
||||||
|
// TODO hydration
|
||||||
|
render(vnode, container, isSVG)
|
||||||
|
|
||||||
|
if (container instanceof Element) {
|
||||||
|
container.removeAttribute('v-cloak')
|
||||||
|
container.setAttribute('data-v-app', '')
|
||||||
|
}
|
||||||
|
|
||||||
|
isMounted = true
|
||||||
|
app._container = container
|
||||||
|
// for devtools and telemetry
|
||||||
|
;(container as any).__vue_app__ = app
|
||||||
|
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
|
||||||
|
devtoolsInitApp(app, version)
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance.proxy!
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.ctx._compat_destroy = app.unmount
|
||||||
|
|
||||||
|
return instance.proxy!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dev only
|
||||||
|
export function installLegacyConfigTraps(config: AppConfig) {
|
||||||
|
const legacyConfigOptions: Record<string, DeprecationTypes> = {
|
||||||
|
silent: DeprecationTypes.CONFIG_SILENT,
|
||||||
|
devtools: DeprecationTypes.CONFIG_DEVTOOLS,
|
||||||
|
ignoredElements: DeprecationTypes.CONFIG_IGNORED_ELEMENTS,
|
||||||
|
keyCodes: DeprecationTypes.CONFIG_KEY_CODES,
|
||||||
|
productionTip: DeprecationTypes.CONFIG_PRODUCTION_TIP
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(legacyConfigOptions).forEach(key => {
|
||||||
|
let val = (config as any)[key]
|
||||||
|
Object.defineProperty(config, key, {
|
||||||
|
enumerable: true,
|
||||||
|
get() {
|
||||||
|
return val
|
||||||
|
},
|
||||||
|
set(newVal) {
|
||||||
|
if (!isCopyingConfig) {
|
||||||
|
warnDeprecation(legacyConfigOptions[key])
|
||||||
|
}
|
||||||
|
val = newVal
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
import { AppConfig } from '../apiCreateApp'
|
|
||||||
import { DeprecationTypes, warnDeprecation } from './deprecations'
|
|
||||||
import { isCopyingConfig } from './global'
|
|
||||||
|
|
||||||
// legacy config warnings
|
|
||||||
export type LegacyConfig = {
|
|
||||||
/**
|
|
||||||
* @deprecated `config.silent` option has been removed
|
|
||||||
*/
|
|
||||||
silent?: boolean
|
|
||||||
/**
|
|
||||||
* @deprecated use __VUE_PROD_DEVTOOLS__ compile-time feature flag instead
|
|
||||||
* https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags
|
|
||||||
*/
|
|
||||||
devtools?: boolean
|
|
||||||
/**
|
|
||||||
* @deprecated use `config.isCustomElement` instead
|
|
||||||
* https://v3.vuejs.org/guide/migration/global-api.html#config-ignoredelements-is-now-config-iscustomelement
|
|
||||||
*/
|
|
||||||
ignoredElements?: (string | RegExp)[]
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
* https://v3.vuejs.org/guide/migration/keycode-modifiers.html
|
|
||||||
*/
|
|
||||||
keyCodes?: Record<string, number | number[]>
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
* https://v3.vuejs.org/guide/migration/global-api.html#config-productiontip-removed
|
|
||||||
*/
|
|
||||||
productionTip?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export function installLegacyConfigTraps(config: AppConfig) {
|
|
||||||
const legacyConfigOptions: Record<string, DeprecationTypes> = {
|
|
||||||
silent: DeprecationTypes.CONFIG_SILENT,
|
|
||||||
devtools: DeprecationTypes.CONFIG_DEVTOOLS,
|
|
||||||
ignoredElements: DeprecationTypes.CONFIG_IGNORED_ELEMENTS,
|
|
||||||
keyCodes: DeprecationTypes.CONFIG_KEY_CODES,
|
|
||||||
productionTip: DeprecationTypes.CONFIG_PRODUCTION_TIP
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(legacyConfigOptions).forEach(key => {
|
|
||||||
let val = (config as any)[key]
|
|
||||||
Object.defineProperty(config, key, {
|
|
||||||
enumerable: true,
|
|
||||||
get() {
|
|
||||||
return val
|
|
||||||
},
|
|
||||||
set(newVal) {
|
|
||||||
if (!isCopyingConfig) {
|
|
||||||
warnDeprecation(legacyConfigOptions[key])
|
|
||||||
}
|
|
||||||
val = newVal
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,141 +0,0 @@
|
|||||||
import { isFunction } from '@vue/shared'
|
|
||||||
import { App, AppContext } from '../apiCreateApp'
|
|
||||||
import {
|
|
||||||
ComponentOptions,
|
|
||||||
createComponentInstance,
|
|
||||||
finishComponentSetup,
|
|
||||||
setupComponent
|
|
||||||
} from '../component'
|
|
||||||
import { devtoolsInitApp } from '../devtools'
|
|
||||||
import { RootHydrateFunction } from '../hydration'
|
|
||||||
import { RootRenderFunction } from '../renderer'
|
|
||||||
import { cloneVNode, createVNode } from '../vnode'
|
|
||||||
import { warn } from '../warning'
|
|
||||||
import { version } from '..'
|
|
||||||
import { DeprecationTypes, warnDeprecation } from './deprecations'
|
|
||||||
|
|
||||||
export function installCompatMount(
|
|
||||||
app: App,
|
|
||||||
context: AppContext,
|
|
||||||
render: RootRenderFunction,
|
|
||||||
hydrate?: RootHydrateFunction
|
|
||||||
) {
|
|
||||||
let isMounted = false
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vue 2 supports the behavior of creating a component instance but not
|
|
||||||
* mounting it, which is no longer possible in Vue 3 - this internal
|
|
||||||
* function simulates that behavior.
|
|
||||||
*/
|
|
||||||
app._createRoot = options => {
|
|
||||||
const component = app._component
|
|
||||||
const vnode = createVNode(component, options.propsData || null)
|
|
||||||
vnode.appContext = context
|
|
||||||
|
|
||||||
const hasNoRender =
|
|
||||||
!isFunction(component) && !component.render && !component.template
|
|
||||||
const emptyRender = () => {}
|
|
||||||
|
|
||||||
// create root instance
|
|
||||||
const instance = createComponentInstance(vnode, null, null)
|
|
||||||
// suppress "missing render fn" warning since it can't be determined
|
|
||||||
// until $mount is called
|
|
||||||
if (hasNoRender) {
|
|
||||||
instance.render = emptyRender
|
|
||||||
}
|
|
||||||
setupComponent(instance, __NODE_JS__)
|
|
||||||
vnode.component = instance
|
|
||||||
|
|
||||||
// $mount & $destroy
|
|
||||||
// these are defined on ctx and picked up by the $mount/$destroy
|
|
||||||
// public property getters on the instance proxy.
|
|
||||||
// Note: the following assumes DOM environment since the compat build
|
|
||||||
// only targets web. It essentially includes logic for app.mount from
|
|
||||||
// both runtime-core AND runtime-dom.
|
|
||||||
instance.ctx._compat_mount = (selectorOrEl: string | Element) => {
|
|
||||||
if (isMounted) {
|
|
||||||
__DEV__ && warn(`Root instance is already mounted.`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let container: Element
|
|
||||||
if (typeof selectorOrEl === 'string') {
|
|
||||||
// eslint-disable-next-line
|
|
||||||
const result = document.querySelector(selectorOrEl)
|
|
||||||
if (!result) {
|
|
||||||
__DEV__ &&
|
|
||||||
warn(
|
|
||||||
`Failed to mount root instance: selector "${selectorOrEl}" returned null.`
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
container = result
|
|
||||||
} else {
|
|
||||||
if (!selectorOrEl) {
|
|
||||||
__DEV__ &&
|
|
||||||
warn(
|
|
||||||
`Failed to mount root instance: invalid mount target ${selectorOrEl}.`
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
container = selectorOrEl
|
|
||||||
}
|
|
||||||
|
|
||||||
const isSVG = container instanceof SVGElement
|
|
||||||
|
|
||||||
// HMR root reload
|
|
||||||
if (__DEV__) {
|
|
||||||
context.reload = () => {
|
|
||||||
const cloned = cloneVNode(vnode)
|
|
||||||
// compat mode will use instance if not reset to null
|
|
||||||
cloned.component = null
|
|
||||||
render(cloned, container, isSVG)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolve in-DOM template if component did not provide render
|
|
||||||
// and no setup/mixin render functions are provided (by checking
|
|
||||||
// that the instance is still using the placeholder render fn)
|
|
||||||
if (hasNoRender && instance.render === emptyRender) {
|
|
||||||
// root directives check
|
|
||||||
if (__DEV__) {
|
|
||||||
for (let i = 0; i < container.attributes.length; i++) {
|
|
||||||
const attr = container.attributes[i]
|
|
||||||
if (attr.name !== 'v-cloak' && /^(v-|:|@)/.test(attr.name)) {
|
|
||||||
warnDeprecation(DeprecationTypes.DOM_TEMPLATE_MOUNT)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
instance.render = null
|
|
||||||
;(component as ComponentOptions).template = container.innerHTML
|
|
||||||
finishComponentSetup(instance, __NODE_JS__, true /* skip options */)
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear content before mounting
|
|
||||||
container.innerHTML = ''
|
|
||||||
|
|
||||||
// TODO hydration
|
|
||||||
render(vnode, container, isSVG)
|
|
||||||
|
|
||||||
if (container instanceof Element) {
|
|
||||||
container.removeAttribute('v-cloak')
|
|
||||||
container.setAttribute('data-v-app', '')
|
|
||||||
}
|
|
||||||
|
|
||||||
isMounted = true
|
|
||||||
app._container = container
|
|
||||||
// for devtools and telemetry
|
|
||||||
;(container as any).__vue_app__ = app
|
|
||||||
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
|
|
||||||
devtoolsInitApp(app, version)
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance.proxy!
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.ctx._compat_destroy = app.unmount
|
|
||||||
|
|
||||||
return instance.proxy!
|
|
||||||
}
|
|
||||||
}
|
|
34
packages/runtime-core/src/compat/instance.ts
Normal file
34
packages/runtime-core/src/compat/instance.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { extend, NOOP } from '@vue/shared'
|
||||||
|
import { PublicPropertiesMap } from '../componentPublicInstance'
|
||||||
|
import { DeprecationTypes, warnDeprecation } from './deprecations'
|
||||||
|
|
||||||
|
export function installCompatInstanceProperties(map: PublicPropertiesMap) {
|
||||||
|
const set = (target: any, key: any, val: any) => {
|
||||||
|
target[key] = val
|
||||||
|
}
|
||||||
|
|
||||||
|
const del = (target: any, key: any) => {
|
||||||
|
delete target[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
extend(map, {
|
||||||
|
$set: () => {
|
||||||
|
__DEV__ && warnDeprecation(DeprecationTypes.INSTANCE_SET)
|
||||||
|
return set
|
||||||
|
},
|
||||||
|
$delete: () => {
|
||||||
|
__DEV__ && warnDeprecation(DeprecationTypes.INSTANCE_DELETE)
|
||||||
|
return del
|
||||||
|
},
|
||||||
|
$mount: i => {
|
||||||
|
__DEV__ && warnDeprecation(DeprecationTypes.INSTANCE_MOUNT)
|
||||||
|
// root mount override from ./global.ts in installCompatMount
|
||||||
|
return i.ctx._compat_mount || NOOP
|
||||||
|
},
|
||||||
|
$destroy: i => {
|
||||||
|
__DEV__ && warnDeprecation(DeprecationTypes.INSTANCE_DESTROY)
|
||||||
|
// root destroy override from ./global.ts in installCompatMount
|
||||||
|
return i.ctx._compat_destroy || NOOP
|
||||||
|
}
|
||||||
|
} as PublicPropertiesMap)
|
||||||
|
}
|
@ -41,7 +41,8 @@ import { markAttrsAccessed } from './componentRenderUtils'
|
|||||||
import { currentRenderingInstance } from './componentRenderContext'
|
import { currentRenderingInstance } from './componentRenderContext'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
import { UnionToIntersection } from './helpers/typeUtils'
|
import { UnionToIntersection } from './helpers/typeUtils'
|
||||||
import { warnDeprecation, DeprecationTypes } from './compat/deprecations'
|
import { installCompatInstanceProperties } from './compat/instance'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom properties added to component instances in any way and can be accessed through `this`
|
* Custom properties added to component instances in any way and can be accessed through `this`
|
||||||
*
|
*
|
||||||
@ -202,7 +203,10 @@ export type ComponentPublicInstance<
|
|||||||
M &
|
M &
|
||||||
ComponentCustomProperties
|
ComponentCustomProperties
|
||||||
|
|
||||||
type PublicPropertiesMap = Record<string, (i: ComponentInternalInstance) => any>
|
export type PublicPropertiesMap = Record<
|
||||||
|
string,
|
||||||
|
(i: ComponentInternalInstance) => any
|
||||||
|
>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* #2437 In Vue 3, functional components do not have a public instance proxy but
|
* #2437 In Vue 3, functional components do not have a public instance proxy but
|
||||||
@ -235,22 +239,7 @@ const publicPropertiesMap: PublicPropertiesMap = extend(Object.create(null), {
|
|||||||
} as PublicPropertiesMap)
|
} as PublicPropertiesMap)
|
||||||
|
|
||||||
if (__COMPAT__) {
|
if (__COMPAT__) {
|
||||||
extend(publicPropertiesMap, {
|
installCompatInstanceProperties(publicPropertiesMap)
|
||||||
$mount: i => {
|
|
||||||
if (__DEV__) {
|
|
||||||
warnDeprecation(DeprecationTypes.$MOUNT)
|
|
||||||
}
|
|
||||||
// root mount override from apiCreateApp.ts
|
|
||||||
return i.ctx._compat_mount || NOOP
|
|
||||||
},
|
|
||||||
$destroy: i => {
|
|
||||||
if (__DEV__) {
|
|
||||||
warnDeprecation(DeprecationTypes.$DESTROY)
|
|
||||||
}
|
|
||||||
// root destroy override from apiCreateApp.ts
|
|
||||||
return i.ctx._compat_destroy || NOOP
|
|
||||||
}
|
|
||||||
} as PublicPropertiesMap)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const enum AccessTypes {
|
const enum AccessTypes {
|
||||||
|
@ -78,7 +78,7 @@ export const createApp = ((...args) => {
|
|||||||
for (let i = 0; i < container.attributes.length; i++) {
|
for (let i = 0; i < container.attributes.length; i++) {
|
||||||
const attr = container.attributes[i]
|
const attr = container.attributes[i]
|
||||||
if (attr.name !== 'v-cloak' && /^(v-|:|@)/.test(attr.name)) {
|
if (attr.name !== 'v-cloak' && /^(v-|:|@)/.test(attr.name)) {
|
||||||
warnDeprecation(DeprecationTypes.DOM_TEMPLATE_MOUNT)
|
warnDeprecation(DeprecationTypes.GLOBAL_DOM_TEMPLATE_MOUNT)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
registerRuntimeCompiler,
|
registerRuntimeCompiler,
|
||||||
RenderFunction,
|
RenderFunction,
|
||||||
warn,
|
warn,
|
||||||
|
createApp,
|
||||||
createCompatVue
|
createCompatVue
|
||||||
} from '@vue/runtime-dom'
|
} from '@vue/runtime-dom'
|
||||||
import { isString, NOOP, generateCodeFrame, extend } from '@vue/shared'
|
import { isString, NOOP, generateCodeFrame, extend } from '@vue/shared'
|
||||||
@ -91,7 +92,7 @@ function compileToFunction(
|
|||||||
|
|
||||||
registerRuntimeCompiler(compileToFunction)
|
registerRuntimeCompiler(compileToFunction)
|
||||||
|
|
||||||
const Vue = createCompatVue()
|
const Vue = createCompatVue(createApp)
|
||||||
|
|
||||||
Vue.compile = compileToFunction
|
Vue.compile = compileToFunction
|
||||||
extend(Vue, runtimeDom)
|
extend(Vue, runtimeDom)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user