2021-04-11 20:53:43 +00:00
|
|
|
import {
|
|
|
|
isReactive,
|
|
|
|
reactive,
|
|
|
|
track,
|
|
|
|
TrackOpTypes,
|
|
|
|
trigger,
|
|
|
|
TriggerOpTypes
|
|
|
|
} from '@vue/reactivity'
|
|
|
|
import {
|
|
|
|
isFunction,
|
|
|
|
extend,
|
|
|
|
NOOP,
|
|
|
|
EMPTY_OBJ,
|
|
|
|
isArray,
|
2021-04-28 16:29:51 +00:00
|
|
|
isObject,
|
|
|
|
isString
|
2021-04-11 20:53:43 +00:00
|
|
|
} from '@vue/shared'
|
2021-04-05 22:13:29 +00:00
|
|
|
import { warn } from '../warning'
|
|
|
|
import { cloneVNode, createVNode } from '../vnode'
|
|
|
|
import { RootRenderFunction } from '../renderer'
|
|
|
|
import { RootHydrateFunction } from '../hydration'
|
|
|
|
import {
|
|
|
|
App,
|
|
|
|
AppConfig,
|
|
|
|
AppContext,
|
|
|
|
CreateAppFunction,
|
|
|
|
Plugin
|
|
|
|
} from '../apiCreateApp'
|
|
|
|
import {
|
|
|
|
Component,
|
|
|
|
ComponentOptions,
|
|
|
|
createComponentInstance,
|
|
|
|
finishComponentSetup,
|
|
|
|
isRuntimeOnly,
|
|
|
|
setupComponent
|
|
|
|
} from '../component'
|
2021-04-11 20:53:43 +00:00
|
|
|
import { RenderFunction, mergeOptions } from '../componentOptions'
|
2021-04-05 21:09:22 +00:00
|
|
|
import { ComponentPublicInstance } from '../componentPublicInstance'
|
2021-04-28 21:21:02 +00:00
|
|
|
import { devtoolsInitApp, devtoolsUnmountApp } from '../devtools'
|
2021-04-05 21:09:22 +00:00
|
|
|
import { Directive } from '../directives'
|
|
|
|
import { nextTick } from '../scheduler'
|
2021-04-05 22:13:29 +00:00
|
|
|
import { version } from '..'
|
2021-04-27 21:34:19 +00:00
|
|
|
import { LegacyConfig, legacyOptionMergeStrats } from './globalConfig'
|
2021-04-06 15:57:10 +00:00
|
|
|
import { LegacyDirective } from './customDirective'
|
2021-04-07 19:38:04 +00:00
|
|
|
import {
|
2021-04-12 22:47:50 +00:00
|
|
|
warnDeprecation,
|
|
|
|
DeprecationTypes,
|
2021-04-07 19:38:04 +00:00
|
|
|
assertCompatEnabled,
|
|
|
|
configureCompat,
|
|
|
|
isCompatEnabled,
|
|
|
|
softAssertCompatEnabled
|
|
|
|
} from './compatConfig'
|
2021-04-27 21:34:19 +00:00
|
|
|
import { LegacyPublicInstance } from './instance'
|
2021-04-05 21:09:22 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @deprecated the default `Vue` export has been removed in Vue 3. The type for
|
|
|
|
* the default export is provided only for migration purposes. Please use
|
|
|
|
* named imports instead - e.g. `import { createApp } from 'vue'`.
|
|
|
|
*/
|
|
|
|
export type CompatVue = Pick<App, 'version' | 'component' | 'directive'> & {
|
2021-04-27 21:34:19 +00:00
|
|
|
configureCompat: typeof configureCompat
|
|
|
|
|
2021-04-05 21:09:22 +00:00
|
|
|
// no inference here since these types are not meant for actual use - they
|
|
|
|
// are merely here to provide type checks for internal implementation and
|
|
|
|
// information for migration.
|
2021-04-27 21:34:19 +00:00
|
|
|
new (options?: ComponentOptions): LegacyPublicInstance
|
2021-04-05 21:09:22 +00:00
|
|
|
|
|
|
|
version: string
|
2021-04-05 22:13:29 +00:00
|
|
|
config: AppConfig & LegacyConfig
|
2021-04-05 21:09:22 +00:00
|
|
|
|
2021-04-27 21:34:19 +00:00
|
|
|
extend: (options?: ComponentOptions) => CompatVue
|
2021-04-05 21:09:22 +00:00
|
|
|
nextTick: typeof nextTick
|
|
|
|
|
|
|
|
use(plugin: Plugin, ...options: any[]): CompatVue
|
|
|
|
mixin(mixin: ComponentOptions): CompatVue
|
|
|
|
|
|
|
|
component(name: string): Component | undefined
|
|
|
|
component(name: string, component: Component): CompatVue
|
|
|
|
directive(name: string): Directive | undefined
|
|
|
|
directive(name: string, directive: Directive): CompatVue
|
|
|
|
|
|
|
|
compile(template: string): RenderFunction
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @deprecated Vue 3 no longer needs set() for adding new properties.
|
|
|
|
*/
|
|
|
|
set(target: any, key: string | number | symbol, value: any): void
|
|
|
|
/**
|
|
|
|
* @deprecated Vue 3 no longer needs delete() for property deletions.
|
|
|
|
*/
|
|
|
|
delete(target: any, key: string | number | symbol): void
|
|
|
|
/**
|
|
|
|
* @deprecated use `reactive` instead.
|
|
|
|
*/
|
|
|
|
observable: typeof reactive
|
|
|
|
/**
|
|
|
|
* @deprecated filters have been removed from Vue 3.
|
|
|
|
*/
|
2021-04-30 21:15:36 +00:00
|
|
|
filter(name: string, arg?: any): null
|
2021-04-22 18:59:54 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
cid: number
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
options: ComponentOptions
|
2021-04-27 21:34:19 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
super: CompatVue
|
2021-04-05 21:09:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export let isCopyingConfig = false
|
|
|
|
|
|
|
|
// Legacy global Vue constructor
|
2021-04-05 22:13:29 +00:00
|
|
|
export function createCompatVue(
|
|
|
|
createApp: CreateAppFunction<Element>
|
|
|
|
): CompatVue {
|
2021-04-05 21:09:22 +00:00
|
|
|
const Vue: CompatVue = function Vue(options: ComponentOptions = {}) {
|
|
|
|
return createCompatApp(options, Vue)
|
|
|
|
} as any
|
|
|
|
|
|
|
|
const singletonApp = createApp({})
|
|
|
|
|
|
|
|
function createCompatApp(options: ComponentOptions = {}, Ctor: any) {
|
2021-04-09 22:52:14 +00:00
|
|
|
assertCompatEnabled(DeprecationTypes.GLOBAL_MOUNT, null)
|
2021-04-07 19:38:04 +00:00
|
|
|
|
2021-04-06 19:02:07 +00:00
|
|
|
const { data } = options
|
2021-04-07 19:38:04 +00:00
|
|
|
if (
|
|
|
|
data &&
|
|
|
|
!isFunction(data) &&
|
2021-04-09 22:52:14 +00:00
|
|
|
softAssertCompatEnabled(DeprecationTypes.OPTIONS_DATA_FN, null)
|
2021-04-07 19:38:04 +00:00
|
|
|
) {
|
2021-04-06 19:02:07 +00:00
|
|
|
options.data = () => data
|
|
|
|
}
|
|
|
|
|
2021-04-05 21:09:22 +00:00
|
|
|
const app = createApp(options)
|
|
|
|
|
2021-04-06 15:57:10 +00:00
|
|
|
// copy over asset registries and deopt flag
|
2021-04-30 21:15:36 +00:00
|
|
|
;['mixins', 'components', 'directives', 'filters', 'deopt'].forEach(key => {
|
2021-04-06 15:57:10 +00:00
|
|
|
// @ts-ignore
|
|
|
|
app._context[key] = singletonApp._context[key]
|
|
|
|
})
|
|
|
|
|
2021-04-05 21:09:22 +00:00
|
|
|
// copy over global config mutations
|
|
|
|
isCopyingConfig = true
|
|
|
|
for (const key in singletonApp.config) {
|
2021-04-26 16:21:36 +00:00
|
|
|
if (key === 'isNativeTag') continue
|
2021-04-05 21:09:22 +00:00
|
|
|
if (
|
2021-04-26 16:21:36 +00:00
|
|
|
isRuntimeOnly() &&
|
|
|
|
(key === 'isCustomElement' || key === 'compilerOptions')
|
2021-04-05 21:09:22 +00:00
|
|
|
) {
|
2021-04-26 16:21:36 +00:00
|
|
|
continue
|
2021-04-05 21:09:22 +00:00
|
|
|
}
|
2021-04-28 16:29:51 +00:00
|
|
|
const val = singletonApp.config[key as keyof AppConfig]
|
2021-04-26 16:21:36 +00:00
|
|
|
// @ts-ignore
|
2021-04-28 16:29:51 +00:00
|
|
|
app.config[key] = val
|
|
|
|
|
|
|
|
// compat for runtime ignoredElements -> isCustomElement
|
|
|
|
if (
|
|
|
|
key === 'ignoredElements' &&
|
|
|
|
isCompatEnabled(DeprecationTypes.CONFIG_IGNORED_ELEMENTS, null) &&
|
|
|
|
!isRuntimeOnly() &&
|
|
|
|
isArray(val)
|
|
|
|
) {
|
|
|
|
app.config.compilerOptions.isCustomElement = tag => {
|
|
|
|
return val.some(v => (isString(v) ? v === tag : v.test(tag)))
|
|
|
|
}
|
|
|
|
}
|
2021-04-05 21:09:22 +00:00
|
|
|
}
|
|
|
|
isCopyingConfig = false
|
|
|
|
|
|
|
|
// copy prototype augmentations as config.globalProperties
|
2021-04-11 20:53:43 +00:00
|
|
|
if (isCompatEnabled(DeprecationTypes.GLOBAL_PROTOTYPE, null)) {
|
2021-04-22 21:30:54 +00:00
|
|
|
app.config.globalProperties = Ctor.prototype
|
2021-04-11 20:53:43 +00:00
|
|
|
}
|
2021-04-05 22:13:29 +00:00
|
|
|
let hasPrototypeAugmentations = false
|
2021-04-05 21:09:22 +00:00
|
|
|
for (const key in Ctor.prototype) {
|
2021-04-05 22:13:29 +00:00
|
|
|
if (key !== 'constructor') {
|
|
|
|
hasPrototypeAugmentations = true
|
2021-04-11 20:53:43 +00:00
|
|
|
break
|
2021-04-07 19:38:04 +00:00
|
|
|
}
|
2021-04-05 21:09:22 +00:00
|
|
|
}
|
2021-04-07 19:38:04 +00:00
|
|
|
if (__DEV__ && hasPrototypeAugmentations) {
|
2021-04-09 22:52:14 +00:00
|
|
|
warnDeprecation(DeprecationTypes.GLOBAL_PROTOTYPE, null)
|
2021-04-05 22:13:29 +00:00
|
|
|
}
|
2021-04-05 21:09:22 +00:00
|
|
|
|
|
|
|
const vm = app._createRoot!(options)
|
|
|
|
if (options.el) {
|
|
|
|
return (vm as any).$mount(options.el)
|
|
|
|
} else {
|
|
|
|
return vm
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Vue.version = __VERSION__
|
|
|
|
Vue.config = singletonApp.config
|
2021-04-07 19:38:04 +00:00
|
|
|
Vue.nextTick = nextTick
|
2021-04-22 18:59:54 +00:00
|
|
|
Vue.options = { _base: Vue }
|
|
|
|
|
|
|
|
let cid = 1
|
|
|
|
Vue.cid = cid
|
2021-04-05 21:09:22 +00:00
|
|
|
|
2021-04-27 21:34:19 +00:00
|
|
|
const extendCache = new WeakMap()
|
|
|
|
|
2021-04-22 18:59:54 +00:00
|
|
|
function extendCtor(this: any, extendOptions: ComponentOptions = {}) {
|
2021-04-09 22:52:14 +00:00
|
|
|
assertCompatEnabled(DeprecationTypes.GLOBAL_EXTEND, null)
|
2021-04-22 18:59:54 +00:00
|
|
|
if (isFunction(extendOptions)) {
|
|
|
|
extendOptions = extendOptions.options
|
|
|
|
}
|
2021-04-07 19:38:04 +00:00
|
|
|
|
2021-04-27 21:34:19 +00:00
|
|
|
if (extendCache.has(extendOptions)) {
|
|
|
|
return extendCache.get(extendOptions)
|
|
|
|
}
|
|
|
|
|
2021-04-22 18:59:54 +00:00
|
|
|
const Super = this
|
2021-04-05 21:09:22 +00:00
|
|
|
function SubVue(inlineOptions?: ComponentOptions) {
|
|
|
|
if (!inlineOptions) {
|
2021-04-27 21:34:19 +00:00
|
|
|
return createCompatApp(SubVue.options, SubVue)
|
2021-04-05 21:09:22 +00:00
|
|
|
} else {
|
|
|
|
return createCompatApp(
|
2021-04-27 21:34:19 +00:00
|
|
|
mergeOptions(
|
|
|
|
extend({}, SubVue.options),
|
|
|
|
inlineOptions,
|
|
|
|
null,
|
|
|
|
legacyOptionMergeStrats as any
|
|
|
|
),
|
2021-04-05 21:09:22 +00:00
|
|
|
SubVue
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2021-04-27 21:34:19 +00:00
|
|
|
SubVue.super = Super
|
2021-04-05 21:09:22 +00:00
|
|
|
SubVue.prototype = Object.create(Vue.prototype)
|
|
|
|
SubVue.prototype.constructor = SubVue
|
2021-04-27 21:34:19 +00:00
|
|
|
|
|
|
|
// clone non-primitive base option values for edge case of mutating
|
|
|
|
// extended options
|
|
|
|
const mergeBase: any = {}
|
|
|
|
for (const key in Super.options) {
|
|
|
|
const superValue = Super.options[key]
|
|
|
|
mergeBase[key] = isArray(superValue)
|
|
|
|
? superValue.slice()
|
|
|
|
: isObject(superValue)
|
|
|
|
? extend(Object.create(null), superValue)
|
|
|
|
: superValue
|
|
|
|
}
|
|
|
|
|
2021-04-22 18:59:54 +00:00
|
|
|
SubVue.options = mergeOptions(
|
2021-04-27 21:34:19 +00:00
|
|
|
mergeBase,
|
|
|
|
extendOptions,
|
|
|
|
null,
|
|
|
|
legacyOptionMergeStrats as any
|
2021-04-22 18:59:54 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
SubVue.options._base = SubVue
|
|
|
|
SubVue.extend = extendCtor.bind(SubVue)
|
|
|
|
SubVue.mixin = Super.mixin
|
|
|
|
SubVue.use = Super.use
|
|
|
|
SubVue.cid = ++cid
|
2021-04-27 21:34:19 +00:00
|
|
|
|
|
|
|
extendCache.set(extendOptions, SubVue)
|
2021-04-05 21:09:22 +00:00
|
|
|
return SubVue
|
2021-04-22 18:59:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Vue.extend = extendCtor.bind(Vue) as any
|
2021-04-05 21:09:22 +00:00
|
|
|
|
|
|
|
Vue.set = (target, key, value) => {
|
2021-04-09 22:52:14 +00:00
|
|
|
assertCompatEnabled(DeprecationTypes.GLOBAL_SET, null)
|
2021-04-05 21:09:22 +00:00
|
|
|
target[key] = value
|
|
|
|
}
|
2021-04-05 22:13:29 +00:00
|
|
|
|
2021-04-05 21:09:22 +00:00
|
|
|
Vue.delete = (target, key) => {
|
2021-04-09 22:52:14 +00:00
|
|
|
assertCompatEnabled(DeprecationTypes.GLOBAL_DELETE, null)
|
2021-04-05 21:09:22 +00:00
|
|
|
delete target[key]
|
|
|
|
}
|
2021-04-05 22:13:29 +00:00
|
|
|
|
2021-04-07 19:38:04 +00:00
|
|
|
Vue.observable = (target: any) => {
|
2021-04-09 22:52:14 +00:00
|
|
|
assertCompatEnabled(DeprecationTypes.GLOBAL_OBSERVABLE, null)
|
2021-04-07 19:38:04 +00:00
|
|
|
return reactive(target)
|
|
|
|
}
|
2021-04-05 21:09:22 +00:00
|
|
|
|
|
|
|
Vue.use = (p, ...options) => {
|
2021-04-22 18:59:54 +00:00
|
|
|
if (p && isFunction(p.install)) {
|
|
|
|
p.install(Vue as any, ...options)
|
|
|
|
} else if (isFunction(p)) {
|
|
|
|
p(Vue as any, ...options)
|
|
|
|
}
|
2021-04-05 21:09:22 +00:00
|
|
|
return Vue
|
|
|
|
}
|
|
|
|
|
|
|
|
Vue.mixin = m => {
|
|
|
|
singletonApp.mixin(m)
|
|
|
|
return Vue
|
|
|
|
}
|
|
|
|
|
2021-04-06 15:57:10 +00:00
|
|
|
Vue.component = ((name: string, comp: Component) => {
|
2021-04-05 21:09:22 +00:00
|
|
|
if (comp) {
|
|
|
|
singletonApp.component(name, comp)
|
|
|
|
return Vue
|
|
|
|
} else {
|
|
|
|
return singletonApp.component(name)
|
|
|
|
}
|
|
|
|
}) as any
|
|
|
|
|
2021-04-06 15:57:10 +00:00
|
|
|
Vue.directive = ((name: string, dir: Directive | LegacyDirective) => {
|
2021-04-05 21:09:22 +00:00
|
|
|
if (dir) {
|
2021-04-06 15:57:10 +00:00
|
|
|
singletonApp.directive(name, dir as Directive)
|
2021-04-05 21:09:22 +00:00
|
|
|
return Vue
|
|
|
|
} else {
|
|
|
|
return singletonApp.directive(name)
|
|
|
|
}
|
|
|
|
}) as any
|
|
|
|
|
2021-04-30 21:15:36 +00:00
|
|
|
Vue.filter = ((name: string, filter?: any) => {
|
|
|
|
if (filter) {
|
|
|
|
singletonApp.filter!(name, filter)
|
|
|
|
return Vue
|
|
|
|
} else {
|
|
|
|
return singletonApp.filter!(name)
|
|
|
|
}
|
2021-04-05 21:09:22 +00:00
|
|
|
}) as any
|
|
|
|
|
2021-04-11 20:53:43 +00:00
|
|
|
// internal utils - these are technically internal but some plugins use it.
|
|
|
|
const util = {
|
|
|
|
warn: __DEV__ ? warn : NOOP,
|
|
|
|
extend,
|
|
|
|
mergeOptions: (parent: any, child: any, vm?: ComponentPublicInstance) =>
|
2021-04-27 21:34:19 +00:00
|
|
|
mergeOptions(
|
|
|
|
parent,
|
|
|
|
child,
|
|
|
|
vm && vm.$,
|
|
|
|
vm ? undefined : (legacyOptionMergeStrats as any)
|
|
|
|
),
|
2021-04-11 20:53:43 +00:00
|
|
|
defineReactive
|
|
|
|
}
|
|
|
|
Object.defineProperty(Vue, 'util', {
|
|
|
|
get() {
|
2021-04-27 21:34:19 +00:00
|
|
|
assertCompatEnabled(DeprecationTypes.GLOBAL_PRIVATE_UTIL, null)
|
2021-04-11 20:53:43 +00:00
|
|
|
return util
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2021-04-07 15:22:56 +00:00
|
|
|
Vue.configureCompat = configureCompat
|
|
|
|
|
2021-04-05 21:09:22 +00:00
|
|
|
return Vue
|
|
|
|
}
|
2021-04-05 22:13:29 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
2021-04-06 16:17:17 +00:00
|
|
|
setupComponent(instance)
|
2021-04-05 22:13:29 +00:00
|
|
|
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.
|
2021-04-27 21:34:19 +00:00
|
|
|
instance.ctx._compat_mount = (selectorOrEl?: string | Element) => {
|
2021-04-05 22:13:29 +00:00
|
|
|
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 {
|
2021-04-27 21:34:19 +00:00
|
|
|
// eslint-disable-next-line
|
|
|
|
container = selectorOrEl || document.createElement('div')
|
2021-04-05 22:13:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)) {
|
2021-04-09 22:52:14 +00:00
|
|
|
warnDeprecation(DeprecationTypes.GLOBAL_MOUNT_CONTAINER, null)
|
2021-04-05 22:13:29 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
instance.render = null
|
|
|
|
;(component as ComponentOptions).template = container.innerHTML
|
2021-04-06 16:17:17 +00:00
|
|
|
finishComponentSetup(instance, false, true /* skip options */)
|
2021-04-05 22:13:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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!
|
|
|
|
}
|
|
|
|
|
2021-04-28 21:21:02 +00:00
|
|
|
instance.ctx._compat_destroy = () => {
|
|
|
|
if (isMounted) {
|
|
|
|
render(null, app._container)
|
|
|
|
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
|
|
|
|
devtoolsUnmountApp(app)
|
|
|
|
}
|
|
|
|
delete app._container.__vue_app__
|
|
|
|
} else if (__DEV__) {
|
|
|
|
warn(`Cannot unmount an app that is not mounted.`)
|
|
|
|
}
|
|
|
|
}
|
2021-04-05 22:13:29 +00:00
|
|
|
|
|
|
|
return instance.proxy!
|
|
|
|
}
|
|
|
|
}
|
2021-04-11 20:53:43 +00:00
|
|
|
|
|
|
|
const methodsToPatch = [
|
|
|
|
'push',
|
|
|
|
'pop',
|
|
|
|
'shift',
|
|
|
|
'unshift',
|
|
|
|
'splice',
|
|
|
|
'sort',
|
|
|
|
'reverse'
|
|
|
|
]
|
|
|
|
|
|
|
|
const patched = new WeakSet<object>()
|
|
|
|
|
|
|
|
function defineReactive(obj: any, key: string, val: any) {
|
|
|
|
// it's possible for the orignial object to be mutated after being defined
|
|
|
|
// and expecting reactivity... we are covering it here because this seems to
|
|
|
|
// be a bit more common.
|
|
|
|
if (isObject(val) && !isReactive(val) && !patched.has(val)) {
|
|
|
|
const reactiveVal = reactive(val)
|
|
|
|
if (isArray(val)) {
|
|
|
|
methodsToPatch.forEach(m => {
|
|
|
|
// @ts-ignore
|
|
|
|
val[m] = (...args: any[]) => {
|
|
|
|
// @ts-ignore
|
|
|
|
Array.prototype[m].call(reactiveVal, ...args)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
Object.keys(val).forEach(key => {
|
2021-04-22 21:30:54 +00:00
|
|
|
try {
|
|
|
|
defineReactiveSimple(val, key, val[key])
|
|
|
|
} catch (e) {}
|
2021-04-11 20:53:43 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const i = obj.$
|
|
|
|
if (i && obj === i.proxy) {
|
|
|
|
// Vue instance, add it to data
|
|
|
|
if (i.data === EMPTY_OBJ) {
|
|
|
|
i.data = reactive({})
|
|
|
|
}
|
|
|
|
i.data[key] = val
|
|
|
|
i.accessCache = Object.create(null)
|
|
|
|
} else if (isReactive(obj)) {
|
|
|
|
obj[key] = val
|
|
|
|
} else {
|
|
|
|
defineReactiveSimple(obj, key, val)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function defineReactiveSimple(obj: any, key: string, val: any) {
|
|
|
|
val = isObject(val) ? reactive(val) : val
|
|
|
|
Object.defineProperty(obj, key, {
|
|
|
|
enumerable: true,
|
|
|
|
configurable: true,
|
|
|
|
get() {
|
|
|
|
track(obj, TrackOpTypes.GET, key)
|
|
|
|
return val
|
|
|
|
},
|
|
|
|
set(newVal) {
|
|
|
|
val = isObject(newVal) ? reactive(newVal) : newVal
|
|
|
|
trigger(obj, TriggerOpTypes.SET, key, newVal)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|