mirror of
https://gitee.com/vuejs/vue.git
synced 2024-11-30 02:57:43 +08:00
rework type annotation strategy: use interface instead
This commit is contained in:
parent
6dc2662b40
commit
1b7ab89a5d
@ -8,6 +8,7 @@
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
flow
|
||||
|
||||
[options]
|
||||
module.name_mapper='^compiler/\(.*\)$' -> '<PROJECT_ROOT>/src/compiler/\1'
|
||||
|
116
flow/declarations.js
Normal file
116
flow/declarations.js
Normal file
@ -0,0 +1,116 @@
|
||||
import type { Config } from '../src/core/config'
|
||||
import type VNode from '../src/core/vdom/vnode'
|
||||
import type Watcher from '../src/core/observer/watcher'
|
||||
|
||||
declare interface Component {
|
||||
// constructor information
|
||||
static cid: number;
|
||||
static options: Object;
|
||||
// extend
|
||||
static extend: (options: Object) => Function;
|
||||
// assets
|
||||
static directive: (id: string, def?: Function | Object) => Function | Object | void;
|
||||
static component: (id: string, def?: Class<Component> | Object) => Class<Component>;
|
||||
static transition: (id: string, def?: Object) => Object | void;
|
||||
static filter: (id: string, def?: Function) => Function | void;
|
||||
|
||||
// public properties
|
||||
$el: Element | void;
|
||||
$data: Object;
|
||||
$options: Object;
|
||||
$parent: Component | void;
|
||||
$root: Component;
|
||||
$children: Array<Component>;
|
||||
$refs: { [key: string]: Component | Element | Array<Component | Element> | void };
|
||||
$slots: { [key: string]: Array<VNode> };
|
||||
$isServer: boolean;
|
||||
|
||||
// public methods
|
||||
$mount: (el?: Element | string) => Component;
|
||||
$forceUpdate: () => void;
|
||||
$destroy: () => void;
|
||||
$watch: (expOrFn: string | Function, cb: Function, options?: Object) => Function;
|
||||
$on: (event: string, fn: Function) => Component;
|
||||
$once: (event: string, fn: Function) => Component;
|
||||
$off: (event?: string, fn?: Function) => Component;
|
||||
$emit: (event: string, ...args: Array<any>) => Component;
|
||||
$nextTick: (fn: Function) => void;
|
||||
$createElement: (
|
||||
tag?: string | Component,
|
||||
data?: Object,
|
||||
children?: Array<?VNode> | string,
|
||||
namespace?: string
|
||||
) => VNode;
|
||||
|
||||
// private properties
|
||||
_uid: number;
|
||||
_isVue: true;
|
||||
_renderProxy: Component;
|
||||
_watcher: Watcher;
|
||||
_watchers: Array<Watcher>;
|
||||
_data: Object;
|
||||
_events: Object;
|
||||
_isMounted: boolean;
|
||||
_isDestroyed: boolean;
|
||||
_isBeingDestroyed: boolean;
|
||||
_vnode: ?VNode;
|
||||
_staticTrees: ?Array<VNode>;
|
||||
|
||||
// private methods
|
||||
// lifecycle
|
||||
_mount: () => Component;
|
||||
_update: (vnode: VNode) => void;
|
||||
_updateFromParent: (
|
||||
propsData?: Object,
|
||||
listeners?: { [key: string]: Function | Array<Function> },
|
||||
parentVnode: VNode,
|
||||
renderChildren: Array<VNode> | () => Array<VNode>
|
||||
) => void;
|
||||
// rendering
|
||||
_render: () => VNode;
|
||||
__patch__: (a: Element | VNode | void, b: VNode) => Element;
|
||||
__h__: (
|
||||
tag?: string | Component | Object,
|
||||
data?: Object,
|
||||
children?: Array<?VNode> | string,
|
||||
namespace?: string
|
||||
) => VNode;
|
||||
__toString__: (value: any) => string;
|
||||
__resolveFilter__: (id: string) => Function;
|
||||
__renderList__: (
|
||||
val: any,
|
||||
render: Function
|
||||
) => ?Array<VNode>;
|
||||
__registerRef__: (
|
||||
key: string,
|
||||
ref: Component | Element,
|
||||
vFor: boolean,
|
||||
isRemoval: boolean
|
||||
) => void;
|
||||
|
||||
// allow dynamic method registration
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
declare interface GlobalAPI {
|
||||
cid: number;
|
||||
options: Object;
|
||||
config: Config;
|
||||
util: Object;
|
||||
|
||||
extend: (options: Object) => Function;
|
||||
set: (obj: Object, key: string, value: any) => void;
|
||||
delete: (obj: Object, key: string) => void;
|
||||
nextTick: (fn: Function, context?: Object) => void;
|
||||
use: (plugin: Function | Object) => void;
|
||||
mixin: (mixin: Object) => void;
|
||||
compile: (template: string) => { render: Function, staticRenderFns: Array<Function> };
|
||||
|
||||
directive: (id: string, def?: Function | Object) => Function | Object | void;
|
||||
component: (id: string, def?: Class<Component> | Object) => Class<Component>;
|
||||
transition: (id: string, def?: Object) => Object | void;
|
||||
filter: (id: string, def?: Function) => Function | void;
|
||||
|
||||
// allow dynamic method registration
|
||||
[key: string]: any
|
||||
}
|
@ -1,17 +1,17 @@
|
||||
/*
|
||||
* not type checking this file because flow doesn't like dynamically setting
|
||||
* fields on a class
|
||||
*/
|
||||
/* @flow */
|
||||
|
||||
import config from '../config'
|
||||
import { warn, isPlainObject } from '../util/index'
|
||||
|
||||
export function initAssetRegisters (Vue) {
|
||||
export function initAssetRegisters (Vue: GlobalAPI) {
|
||||
/**
|
||||
* Create asset registration methods.
|
||||
*/
|
||||
config._assetTypes.forEach(type => {
|
||||
Vue[type] = function (id, definition) {
|
||||
Vue[type] = function (
|
||||
id: string,
|
||||
definition: Function | Object
|
||||
): Function | Object | void {
|
||||
if (!definition) {
|
||||
return this.options[type + 's'][id]
|
||||
} else {
|
||||
|
@ -1,10 +1,10 @@
|
||||
/* @flow */
|
||||
|
||||
import type Vue from '../instance/index'
|
||||
import config from '../config'
|
||||
import { init } from '../instance/init'
|
||||
import { warn, mergeOptions } from '../util/index'
|
||||
|
||||
export function initExtend (Vue: Class<Vue>) {
|
||||
export function initExtend (Vue: GlobalAPI) {
|
||||
/**
|
||||
* Each instance constructor, including Vue, has a unique
|
||||
* cid. This enables us to create wrapped "child
|
||||
@ -16,7 +16,7 @@ export function initExtend (Vue: Class<Vue>) {
|
||||
/**
|
||||
* Class inheritance
|
||||
*/
|
||||
Vue.extend = function (extendOptions: Object): Class<any> {
|
||||
Vue.extend = function (extendOptions: Object): Function {
|
||||
extendOptions = extendOptions || {}
|
||||
const Super = this
|
||||
const isFirstExtend = Super.cid === 0
|
||||
@ -34,7 +34,7 @@ export function initExtend (Vue: Class<Vue>) {
|
||||
}
|
||||
}
|
||||
const Sub = function VueComponent (options) {
|
||||
this._init(options)
|
||||
init(this, options)
|
||||
}
|
||||
Sub.prototype = Object.create(Super.prototype)
|
||||
Sub.prototype.constructor = Sub
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
import type Vue from '../instance/index'
|
||||
import config from '../config'
|
||||
import * as util from '../util/index'
|
||||
import { initUse } from './use'
|
||||
@ -9,7 +8,7 @@ import { initExtend } from './extend'
|
||||
import { initAssetRegisters } from './assets'
|
||||
import { set, del } from '../observer/index'
|
||||
|
||||
export function initGlobalAPI (Vue: Class<Vue>) {
|
||||
export function initGlobalAPI (Vue: GlobalAPI) {
|
||||
Vue.config = config
|
||||
Vue.util = util
|
||||
Vue.set = set
|
||||
|
@ -1,9 +1,8 @@
|
||||
/* @flow */
|
||||
|
||||
import type Vue from '../instance/index'
|
||||
import { mergeOptions } from '../util/index'
|
||||
|
||||
export function initMixin (Vue: Class<Vue>) {
|
||||
export function initMixin (Vue: GlobalAPI) {
|
||||
Vue.mixin = function (mixin: Object) {
|
||||
Vue.options = mergeOptions(Vue.options, mixin)
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
/* @flow */
|
||||
|
||||
import type Vue from '../instance/index'
|
||||
import { toArray } from '../util/index'
|
||||
|
||||
export function initUse (Vue: Class<Vue>) {
|
||||
export function initUse (Vue: GlobalAPI) {
|
||||
Vue.use = function (plugin: Function | Object) {
|
||||
/* istanbul ignore if */
|
||||
if (plugin.installed) {
|
||||
|
@ -1,11 +1,9 @@
|
||||
import Vue from './instance/index'
|
||||
import config from './config'
|
||||
import { initGlobalAPI } from './global-api/index'
|
||||
import Vue from './instance/index'
|
||||
|
||||
initGlobalAPI(Vue)
|
||||
|
||||
// defining $isServer flag here because flow cannot handle
|
||||
// Object.defineProperty getters
|
||||
Object.defineProperty(Vue.prototype, '$isServer', {
|
||||
get: () => config._isServer
|
||||
})
|
||||
|
@ -1,10 +1,9 @@
|
||||
/* @flow */
|
||||
|
||||
import type Vue from './index'
|
||||
import { toArray } from '../util/index'
|
||||
import { updateListeners } from '../vdom/helpers'
|
||||
|
||||
export function initEvents (vm: Vue) {
|
||||
export function initEvents (vm: Component) {
|
||||
vm._events = Object.create(null)
|
||||
// init parent attached events
|
||||
const listeners = vm.$options._parentListeners
|
||||
@ -15,37 +14,39 @@ export function initEvents (vm: Vue) {
|
||||
}
|
||||
}
|
||||
|
||||
export function eventsMixin (Vue: Class<Vue>) {
|
||||
Vue.prototype.$on = function (event: string, fn: Function): Vue {
|
||||
(this._events[event] || (this._events[event] = [])).push(fn)
|
||||
return this
|
||||
export function eventsMixin (Vue: Class<Component>) {
|
||||
Vue.prototype.$on = function (event: string, fn: Function): Component {
|
||||
const vm: Component = this
|
||||
;(vm._events[event] || (vm._events[event] = [])).push(fn)
|
||||
return vm
|
||||
}
|
||||
|
||||
Vue.prototype.$once = function (event: string, fn: Function): Vue {
|
||||
const self = this
|
||||
Vue.prototype.$once = function (event: string, fn: Function): Component {
|
||||
const vm: Component = this
|
||||
function on () {
|
||||
self.$off(event, on)
|
||||
fn.apply(this, arguments)
|
||||
vm.$off(event, on)
|
||||
fn.apply(vm, arguments)
|
||||
}
|
||||
on.fn = fn
|
||||
this.$on(event, on)
|
||||
return this
|
||||
vm.$on(event, on)
|
||||
return vm
|
||||
}
|
||||
|
||||
Vue.prototype.$off = function (event?: string, fn?: Function): Vue {
|
||||
Vue.prototype.$off = function (event?: string, fn?: Function): Component {
|
||||
const vm: Component = this
|
||||
// all
|
||||
if (!arguments.length) {
|
||||
this._events = Object.create(null)
|
||||
return this
|
||||
vm._events = Object.create(null)
|
||||
return vm
|
||||
}
|
||||
// specific event
|
||||
const cbs = this._events[event]
|
||||
const cbs = vm._events[event]
|
||||
if (!cbs) {
|
||||
return this
|
||||
return vm
|
||||
}
|
||||
if (arguments.length === 1) {
|
||||
this._events[event] = null
|
||||
return this
|
||||
vm._events[event] = null
|
||||
return vm
|
||||
}
|
||||
// specific handler
|
||||
let cb
|
||||
@ -57,18 +58,19 @@ export function eventsMixin (Vue: Class<Vue>) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return this
|
||||
return vm
|
||||
}
|
||||
|
||||
Vue.prototype.$emit = function (event: string): Vue {
|
||||
let cbs = this._events[event]
|
||||
Vue.prototype.$emit = function (event: string): Component {
|
||||
const vm: Component = this
|
||||
let cbs = vm._events[event]
|
||||
if (cbs) {
|
||||
cbs = cbs.length > 1 ? toArray(cbs) : cbs
|
||||
const args = toArray(arguments, 1)
|
||||
for (let i = 0, l = cbs.length; i < l; i++) {
|
||||
cbs[i].apply(this, args)
|
||||
cbs[i].apply(vm, args)
|
||||
}
|
||||
}
|
||||
return this
|
||||
return vm
|
||||
}
|
||||
}
|
||||
|
@ -1,137 +1,16 @@
|
||||
/* @flow */
|
||||
import { init } from './init'
|
||||
import { stateMixin } from './state'
|
||||
import { renderMixin } from './render'
|
||||
import { eventsMixin } from './events'
|
||||
import { lifecycleMixin } from './lifecycle'
|
||||
|
||||
import type { Config } from '../config'
|
||||
import type VNode from '../vdom/vnode'
|
||||
import type Watcher from '../observer/watcher'
|
||||
|
||||
import { initProxy } from './proxy'
|
||||
import { initState, stateMixin } from './state'
|
||||
import { initRender, renderMixin } from './render'
|
||||
import { initEvents, eventsMixin } from './events'
|
||||
import { initLifecycle, lifecycleMixin, callHook } from './lifecycle'
|
||||
import { mergeOptions } from '../util/index'
|
||||
|
||||
let uid = 0
|
||||
|
||||
export default class Vue {
|
||||
// static properties
|
||||
static cid: number;
|
||||
static options: Object;
|
||||
static config: Config;
|
||||
static util: Object;
|
||||
|
||||
// static methods
|
||||
static set: (obj: Object, key: string, value: any) => void;
|
||||
static delete: (obj: Object, key: string) => void;
|
||||
static nextTick: (fn: Function, context?: Object) => void;
|
||||
static use: (plugin: Function | Object) => void;
|
||||
static mixin: (mixin: Object) => void;
|
||||
static extend: (options: Object) => Class<any>;
|
||||
static compile: (template: string) => { render: Function, staticRenderFns: Array<Function> };
|
||||
|
||||
// assets
|
||||
static directive: (id: string, def?: Function | Object) => Function | Object | void;
|
||||
static component: (id: string, def?: Class<any> | Object) => Class<any>;
|
||||
static transition: (id: string, def?: Object) => Object | void;
|
||||
static filter: (id: string, def?: Function) => Function | void;
|
||||
|
||||
// public properties
|
||||
$el: Element | void;
|
||||
$data: Object;
|
||||
$options: Object;
|
||||
$parent: Vue | void;
|
||||
$root: Vue;
|
||||
$children: Array<Vue>;
|
||||
$refs: { [key: string]: Vue | Element };
|
||||
$slots: { [key: string]: Array<VNode> };
|
||||
$isServer: boolean;
|
||||
|
||||
// public methods
|
||||
$mount: (el?: Element | string) => Vue;
|
||||
$forceUpdate: () => void;
|
||||
$destroy: () => void;
|
||||
$watch: (expOrFn: string | Function, cb: Function, options?: Object) => Function;
|
||||
$on: (event: string, fn: Function) => Vue;
|
||||
$once: (event: string, fn: Function) => Vue;
|
||||
$off: (event?: string, fn?: Function) => Vue;
|
||||
$emit: (event: string, ...args: Array<any>) => Vue;
|
||||
$nextTick: (fn: Function) => void;
|
||||
$createElement: (
|
||||
tag?: string | Vue,
|
||||
data?: Object,
|
||||
children?: Array<?VNode> | string,
|
||||
namespace?: string
|
||||
) => VNode;
|
||||
|
||||
// private properties
|
||||
_uid: number;
|
||||
_isVue: true;
|
||||
_renderProxy: Vue;
|
||||
_watchers: Array<Watcher>;
|
||||
_data: Object;
|
||||
_events: { [key: string]: Array<Function> };
|
||||
_isMounted: boolean;
|
||||
_isDestroyed: boolean;
|
||||
_isBeingDestroyed: boolean;
|
||||
_vnode: ?VNode;
|
||||
_staticTrees: ?Array<VNode>;
|
||||
|
||||
// private methods
|
||||
// lifecycle
|
||||
_mount: () => Vue;
|
||||
_update: (vnode: VNode) => void;
|
||||
_updateFromParent: (propsData?: Object, listeners?: Object, parentVnode: VNode, renderChildren: Array<VNode> | () => Array<VNode>) => void;
|
||||
// rendering
|
||||
_render: () => VNode;
|
||||
__h__: (
|
||||
tag?: string | Vue,
|
||||
data?: Object,
|
||||
children?: Array<?VNode> | string,
|
||||
namespace?: string
|
||||
) => VNode;
|
||||
__toString__: (value: any) => string;
|
||||
__resolveFilter__: (id: string) => Function;
|
||||
__renderList__: (
|
||||
val: any,
|
||||
render: Function
|
||||
) => ?Array<VNode>;
|
||||
__registerRef__: (
|
||||
key: string,
|
||||
ref: Vue | Element,
|
||||
vFor: boolean,
|
||||
isRemoval: boolean
|
||||
) => void;
|
||||
|
||||
constructor (options?: Object) {
|
||||
this._init(options)
|
||||
}
|
||||
|
||||
_init (options?: Object) {
|
||||
// a uid
|
||||
this._uid = uid++
|
||||
// a flag to avoid this being observed
|
||||
this._isVue = true
|
||||
// merge options
|
||||
this.$options = mergeOptions(
|
||||
this.constructor.options,
|
||||
options || {},
|
||||
this
|
||||
)
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
initProxy(this)
|
||||
} else {
|
||||
this._renderProxy = this
|
||||
}
|
||||
initLifecycle(this)
|
||||
initEvents(this)
|
||||
callHook(this, 'init')
|
||||
initState(this)
|
||||
callHook(this, 'created')
|
||||
initRender(this)
|
||||
}
|
||||
function Vue (options) {
|
||||
init(this, options)
|
||||
}
|
||||
|
||||
stateMixin(Vue)
|
||||
eventsMixin(Vue)
|
||||
lifecycleMixin(Vue)
|
||||
renderMixin(Vue)
|
||||
|
||||
export default Vue
|
||||
|
34
src/core/instance/init.js
Normal file
34
src/core/instance/init.js
Normal file
@ -0,0 +1,34 @@
|
||||
/* @flow */
|
||||
|
||||
import { initProxy } from './proxy'
|
||||
import { initState } from './state'
|
||||
import { initRender } from './render'
|
||||
import { initEvents } from './events'
|
||||
import { initLifecycle, callHook } from './lifecycle'
|
||||
import { mergeOptions } from '../util/index'
|
||||
|
||||
let uid = 0
|
||||
|
||||
export function init (vm: Component, options?: Object) {
|
||||
// a uid
|
||||
vm._uid = uid++
|
||||
// a flag to avoid this being observed
|
||||
vm._isVue = true
|
||||
// merge options
|
||||
vm.$options = mergeOptions(
|
||||
vm.constructor.options,
|
||||
options || {},
|
||||
vm
|
||||
)
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
initProxy(vm)
|
||||
} else {
|
||||
vm._renderProxy = vm
|
||||
}
|
||||
initLifecycle(vm)
|
||||
initEvents(vm)
|
||||
callHook(vm, 'init')
|
||||
initState(vm)
|
||||
callHook(vm, 'created')
|
||||
initRender(vm)
|
||||
}
|
@ -1,13 +1,12 @@
|
||||
/* @flow */
|
||||
|
||||
import type Vue from './index'
|
||||
import type VNode from '../vdom/vnode'
|
||||
import Watcher from '../observer/watcher'
|
||||
import { warn, validateProp, remove } from '../util/index'
|
||||
import { observerState } from '../observer/index'
|
||||
import { updateListeners } from '../vdom/helpers'
|
||||
|
||||
export function initLifecycle (vm: Vue) {
|
||||
export function initLifecycle (vm: Component) {
|
||||
const options = vm.$options
|
||||
|
||||
vm.$parent = options.parent
|
||||
@ -24,56 +23,58 @@ export function initLifecycle (vm: Vue) {
|
||||
vm._isBeingDestroyed = false
|
||||
}
|
||||
|
||||
export function lifecycleMixin (Vue: Class<Vue>) {
|
||||
Vue.prototype._mount = function (): Vue {
|
||||
if (!this.$options.render) {
|
||||
this.$options.render = () => this.$createElement('div')
|
||||
export function lifecycleMixin (Vue: Class<Component>) {
|
||||
Vue.prototype._mount = function (): Component {
|
||||
const vm: Component = this
|
||||
if (!vm.$options.render) {
|
||||
vm.$options.render = () => vm.$createElement('div')
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (this.$options.template) {
|
||||
if (vm.$options.template) {
|
||||
warn(
|
||||
'You are using the runtime-only build of Vue where the template ' +
|
||||
'option is not available. Either pre-compile the templates into ' +
|
||||
'render functions, or use the compiler-included build.',
|
||||
this
|
||||
vm
|
||||
)
|
||||
} else {
|
||||
warn(
|
||||
'Failed to mount component: template or render function not defined.',
|
||||
this
|
||||
vm
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
callHook(this, 'beforeMount')
|
||||
this._watcher = new Watcher(this, this._render, this._update)
|
||||
this._update(this._watcher.value)
|
||||
this._isMounted = true
|
||||
callHook(vm, 'beforeMount')
|
||||
vm._watcher = new Watcher(vm, vm._render, vm._update)
|
||||
vm._update(vm._watcher.value)
|
||||
vm._isMounted = true
|
||||
// root instance, call mounted on self
|
||||
if (this.$root === this) {
|
||||
callHook(this, 'mounted')
|
||||
if (vm.$root === vm) {
|
||||
callHook(vm, 'mounted')
|
||||
}
|
||||
return this
|
||||
return vm
|
||||
}
|
||||
|
||||
Vue.prototype._update = function (vnode: VNode) {
|
||||
if (this._isMounted) {
|
||||
callHook(this, 'beforeUpdate')
|
||||
const vm: Component = this
|
||||
if (vm._isMounted) {
|
||||
callHook(vm, 'beforeUpdate')
|
||||
}
|
||||
if (!this._vnode) {
|
||||
if (!vm._vnode) {
|
||||
// Vue.prototype.__patch__ is injected in entry points
|
||||
// based on the rendering backend used.
|
||||
this.$el = this.__patch__(this.$el, vnode)
|
||||
vm.$el = vm.__patch__(vm.$el, vnode)
|
||||
} else {
|
||||
this.$el = this.__patch__(this._vnode, vnode)
|
||||
vm.$el = vm.__patch__(vm._vnode, vnode)
|
||||
}
|
||||
this._vnode = vnode
|
||||
vm._vnode = vnode
|
||||
// update parent vnode element after patch
|
||||
const parentNode = this.$options._parentVnode
|
||||
const parentNode = vm.$options._parentVnode
|
||||
if (parentNode) {
|
||||
parentNode.elm = this.$el
|
||||
parentNode.elm = vm.$el
|
||||
}
|
||||
if (this._isMounted) {
|
||||
callHook(this, 'updated')
|
||||
if (vm._isMounted) {
|
||||
callHook(vm, 'updated')
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,66 +84,65 @@ export function lifecycleMixin (Vue: Class<Vue>) {
|
||||
parentVnode: VNode,
|
||||
renderChildren: Array<VNode> | () => Array<VNode>
|
||||
) {
|
||||
this.$options._parentVnode = parentVnode
|
||||
this.$options._renderChildren = renderChildren
|
||||
const vm: Component = this
|
||||
vm.$options._parentVnode = parentVnode
|
||||
vm.$options._renderChildren = renderChildren
|
||||
// update props
|
||||
if (propsData && this.$options.props) {
|
||||
if (propsData && vm.$options.props) {
|
||||
observerState.shouldConvert = false
|
||||
const propKeys = this.$options.propKeys
|
||||
const propKeys = vm.$options.propKeys
|
||||
for (let i = 0; i < propKeys.length; i++) {
|
||||
const key = propKeys[i]
|
||||
this[key] = validateProp(this, key, propsData)
|
||||
vm[key] = validateProp(vm, key, propsData)
|
||||
}
|
||||
observerState.shouldConvert = true
|
||||
}
|
||||
// update listeners
|
||||
if (listeners) {
|
||||
const oldListeners = this.$options._parentListeners
|
||||
this.$options._parentListeners = listeners
|
||||
const oldListeners = vm.$options._parentListeners
|
||||
vm.$options._parentListeners = listeners
|
||||
updateListeners(listeners, oldListeners || {}, (event, handler) => {
|
||||
this.$on(event, handler)
|
||||
vm.$on(event, handler)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$forceUpdate = function () {
|
||||
this._watcher.update()
|
||||
const vm: Component = this
|
||||
vm._watcher.update()
|
||||
}
|
||||
|
||||
Vue.prototype.$destroy = function () {
|
||||
if (this._isDestroyed) {
|
||||
const vm: Component = this
|
||||
if (vm._isDestroyed) {
|
||||
return
|
||||
}
|
||||
callHook(this, 'beforeDestroy')
|
||||
this._isBeingDestroyed = true
|
||||
callHook(vm, 'beforeDestroy')
|
||||
vm._isBeingDestroyed = true
|
||||
// remove self from parent
|
||||
const parent = this.$parent
|
||||
const parent = vm.$parent
|
||||
if (parent && !parent._isBeingDestroyed) {
|
||||
remove(parent.$children, this)
|
||||
}
|
||||
// unregister ref
|
||||
if (this._ref) {
|
||||
this._context.$refs[this._ref] = undefined
|
||||
remove(parent.$children, vm)
|
||||
}
|
||||
// teardown watchers
|
||||
let i = this._watchers.length
|
||||
let i = vm._watchers.length
|
||||
while (i--) {
|
||||
this._watchers[i].teardown()
|
||||
vm._watchers[i].teardown()
|
||||
}
|
||||
// remove reference from data ob
|
||||
// frozen object may not have observer.
|
||||
if (this._data.__ob__) {
|
||||
this._data.__ob__.removeVm(this)
|
||||
if (vm._data.__ob__) {
|
||||
vm._data.__ob__.removeVm(vm)
|
||||
}
|
||||
// call the last hook...
|
||||
this._isDestroyed = true
|
||||
callHook(this, 'destroyed')
|
||||
vm._isDestroyed = true
|
||||
callHook(vm, 'destroyed')
|
||||
// turn off all instance listeners.
|
||||
this.$off()
|
||||
vm.$off()
|
||||
}
|
||||
}
|
||||
|
||||
export function callHook (vm: Vue, hook: string) {
|
||||
export function callHook (vm: Component, hook: string) {
|
||||
vm.$emit('pre-hook:' + hook)
|
||||
const handlers = vm.$options[hook]
|
||||
if (handlers) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
import type Vue from './index'
|
||||
import type VNode from '../vdom/vnode'
|
||||
import createElement from '../vdom/create-element'
|
||||
import { emptyVNode } from '../vdom/vnode'
|
||||
@ -8,11 +7,13 @@ import { flatten } from '../vdom/helpers'
|
||||
import { bind, remove, isObject, renderString } from 'shared/util'
|
||||
import { resolveAsset, nextTick } from '../util/index'
|
||||
|
||||
export const renderState = {
|
||||
export const renderState: {
|
||||
activeInstance: Component | null
|
||||
} = {
|
||||
activeInstance: null
|
||||
}
|
||||
|
||||
export function initRender (vm: Vue) {
|
||||
export function initRender (vm: Component) {
|
||||
vm._vnode = null
|
||||
vm._staticTrees = null
|
||||
vm.$slots = {}
|
||||
@ -24,26 +25,27 @@ export function initRender (vm: Vue) {
|
||||
}
|
||||
}
|
||||
|
||||
export function renderMixin (Vue: Class<Vue>) {
|
||||
Vue.prototype.$nextTick = function (fn) {
|
||||
export function renderMixin (Vue: Class<Component>) {
|
||||
Vue.prototype.$nextTick = function (fn: Function) {
|
||||
nextTick(fn, this)
|
||||
}
|
||||
|
||||
Vue.prototype._render = function (): VNode {
|
||||
if (!this._isMounted) {
|
||||
const vm: Component = this
|
||||
if (!vm._isMounted) {
|
||||
// render static sub-trees for once on initial render
|
||||
renderStaticTrees(this)
|
||||
renderStaticTrees(vm)
|
||||
}
|
||||
const prev = renderState.activeInstance
|
||||
renderState.activeInstance = this
|
||||
const { render, _renderChildren, _parentVnode } = this.$options
|
||||
renderState.activeInstance = vm
|
||||
const { render, _renderChildren, _parentVnode } = vm.$options
|
||||
// resolve slots. becaues slots are rendered in parent scope,
|
||||
// we set the activeInstance to parent.
|
||||
if (_renderChildren) {
|
||||
resolveSlots(this, _renderChildren)
|
||||
resolveSlots(vm, _renderChildren)
|
||||
}
|
||||
// render self
|
||||
const vnode = render.call(this._renderProxy) || emptyVNode
|
||||
const vnode = render.call(vm._renderProxy) || emptyVNode
|
||||
// set parent
|
||||
vnode.parent = _parentVnode
|
||||
// restore render state
|
||||
@ -97,16 +99,17 @@ export function renderMixin (Vue: Class<Vue>) {
|
||||
vFor: boolean,
|
||||
isRemoval: boolean
|
||||
) {
|
||||
const refs = this.$refs
|
||||
const vm: Component = this
|
||||
const refs = vm.$refs
|
||||
if (isRemoval) {
|
||||
if (vFor) {
|
||||
if (Array.isArray(refs[key])) {
|
||||
remove(refs[key], ref)
|
||||
} else {
|
||||
refs[key] = undefined
|
||||
}
|
||||
} else {
|
||||
if (vFor) {
|
||||
if (refs[key]) {
|
||||
if (Array.isArray(refs[key])) {
|
||||
refs[key].push(ref)
|
||||
} else {
|
||||
refs[key] = [ref]
|
||||
@ -118,7 +121,7 @@ export function renderMixin (Vue: Class<Vue>) {
|
||||
}
|
||||
}
|
||||
|
||||
function renderStaticTrees (vm: Vue) {
|
||||
function renderStaticTrees (vm: Component) {
|
||||
const staticRenderFns = vm.$options.staticRenderFns
|
||||
if (staticRenderFns) {
|
||||
const trees = vm._staticTrees = new Array(staticRenderFns.length)
|
||||
@ -128,7 +131,7 @@ function renderStaticTrees (vm: Vue) {
|
||||
}
|
||||
}
|
||||
|
||||
function resolveSlots (vm: Vue, renderChildren: () => Array<?VNode> | void) {
|
||||
function resolveSlots (vm: Component, renderChildren: () => Array<?VNode> | void) {
|
||||
if (renderChildren) {
|
||||
const children = flatten(renderChildren())
|
||||
const slots = {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Not type checking this file because flow doesn't play well with Object.defineProperty */
|
||||
/* @flow */
|
||||
|
||||
import Watcher from '../observer/watcher'
|
||||
import Dep from '../observer/dep'
|
||||
@ -18,7 +18,7 @@ import {
|
||||
noop
|
||||
} from '../util/index'
|
||||
|
||||
export function initState (vm) {
|
||||
export function initState (vm: Component) {
|
||||
vm._watchers = []
|
||||
initProps(vm)
|
||||
initData(vm)
|
||||
@ -27,7 +27,7 @@ export function initState (vm) {
|
||||
initWatch(vm)
|
||||
}
|
||||
|
||||
function initProps (vm) {
|
||||
function initProps (vm: Component) {
|
||||
const props = vm.$options.props
|
||||
const propsData = vm.$options.propsData
|
||||
if (props) {
|
||||
@ -43,7 +43,7 @@ function initProps (vm) {
|
||||
}
|
||||
}
|
||||
|
||||
function initData (vm) {
|
||||
function initData (vm: Component) {
|
||||
let data = vm.$options.data
|
||||
data = vm._data = typeof data === 'function'
|
||||
? data()
|
||||
@ -65,35 +65,38 @@ function initData (vm) {
|
||||
observe(data, vm)
|
||||
}
|
||||
|
||||
function initComputed (vm) {
|
||||
const computedSharedDefinition = {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
get: noop,
|
||||
set: noop
|
||||
}
|
||||
|
||||
function initComputed (vm: Component) {
|
||||
const computed = vm.$options.computed
|
||||
if (computed) {
|
||||
for (const key in computed) {
|
||||
const userDef = computed[key]
|
||||
const def = {
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
}
|
||||
if (typeof userDef === 'function') {
|
||||
def.get = makeComputedGetter(userDef, vm)
|
||||
def.set = noop
|
||||
computedSharedDefinition.get = makeComputedGetter(userDef, vm)
|
||||
computedSharedDefinition.set = noop
|
||||
} else {
|
||||
def.get = userDef.get
|
||||
computedSharedDefinition.get = userDef.get
|
||||
? userDef.cache !== false
|
||||
? makeComputedGetter(userDef.get, vm)
|
||||
: bind(userDef.get, vm)
|
||||
: noop
|
||||
def.set = userDef.set
|
||||
computedSharedDefinition.set = userDef.set
|
||||
? bind(userDef.set, vm)
|
||||
: noop
|
||||
}
|
||||
Object.defineProperty(vm, key, def)
|
||||
Object.defineProperty(vm, key, computedSharedDefinition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeComputedGetter (getter, owner) {
|
||||
const watcher = new Watcher(owner, getter, null, {
|
||||
function makeComputedGetter (getter: Function, owner: Component): Function {
|
||||
const watcher = new Watcher(owner, getter, noop, {
|
||||
lazy: true
|
||||
})
|
||||
return function computedGetter () {
|
||||
@ -107,7 +110,7 @@ function makeComputedGetter (getter, owner) {
|
||||
}
|
||||
}
|
||||
|
||||
function initMethods (vm) {
|
||||
function initMethods (vm: Component) {
|
||||
const methods = vm.$options.methods
|
||||
if (methods) {
|
||||
for (const key in methods) {
|
||||
@ -116,7 +119,7 @@ function initMethods (vm) {
|
||||
}
|
||||
}
|
||||
|
||||
function initWatch (vm) {
|
||||
function initWatch (vm: Component) {
|
||||
const watch = vm.$options.watch
|
||||
if (watch) {
|
||||
for (const key in watch) {
|
||||
@ -132,7 +135,7 @@ function initWatch (vm) {
|
||||
}
|
||||
}
|
||||
|
||||
function createWatcher (vm, key, handler) {
|
||||
function createWatcher (vm: Component, key: string, handler: any) {
|
||||
let options
|
||||
if (isPlainObject(handler)) {
|
||||
options = handler
|
||||
@ -144,24 +147,32 @@ function createWatcher (vm, key, handler) {
|
||||
vm.$watch(key, handler, options)
|
||||
}
|
||||
|
||||
export function stateMixin (Vue) {
|
||||
Object.defineProperty(Vue.prototype, '$data', {
|
||||
get () {
|
||||
return this._data
|
||||
},
|
||||
set (newData) {
|
||||
if (newData !== this._data) {
|
||||
setData(this, newData)
|
||||
}
|
||||
export function stateMixin (Vue: Class<Component>) {
|
||||
// flow somehow has problems with directly declared definition object
|
||||
// when using Object.defineProperty, so we have to procedurally build up
|
||||
// the object here.
|
||||
const dataDef = {}
|
||||
dataDef.get = function () {
|
||||
return this._data
|
||||
}
|
||||
dataDef.set = function (newData: Object) {
|
||||
if (newData !== this._data) {
|
||||
setData(this, newData)
|
||||
}
|
||||
})
|
||||
}
|
||||
Object.defineProperty(Vue.prototype, '$data', dataDef)
|
||||
|
||||
Vue.prototype.$watch = function (expOrFn, cb, options) {
|
||||
Vue.prototype.$watch = function (
|
||||
expOrFn: string | Function,
|
||||
cb: Function,
|
||||
options?: Object
|
||||
): Function {
|
||||
const vm: Component = this
|
||||
options = options || {}
|
||||
options.user = true
|
||||
const watcher = new Watcher(this, expOrFn, cb, options)
|
||||
const watcher = new Watcher(vm, expOrFn, cb, options)
|
||||
if (options.immediate) {
|
||||
cb.call(this, watcher.value)
|
||||
cb.call(vm, watcher.value)
|
||||
}
|
||||
return function unwatchFn () {
|
||||
watcher.teardown()
|
||||
@ -169,7 +180,7 @@ export function stateMixin (Vue) {
|
||||
}
|
||||
}
|
||||
|
||||
function setData (vm, newData) {
|
||||
function setData (vm: Component, newData: Object) {
|
||||
newData = newData || {}
|
||||
const oldData = vm._data
|
||||
vm._data = newData
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
import type Vue from '../instance/index'
|
||||
import config from '../config'
|
||||
import Dep from './dep'
|
||||
import { arrayMethods } from './array'
|
||||
@ -36,7 +35,7 @@ export const observerState = {
|
||||
export class Observer {
|
||||
value: any;
|
||||
dep: Dep;
|
||||
vms: ?Array<Vue>;
|
||||
vms: ?Array<Component>;
|
||||
|
||||
constructor (value: any) {
|
||||
this.value = value
|
||||
@ -81,7 +80,7 @@ export class Observer {
|
||||
* digest the watchers. This is only called when the object
|
||||
* is observed as an instance's root $data.
|
||||
*/
|
||||
addVm (vm: Vue) {
|
||||
addVm (vm: Component) {
|
||||
(this.vms || (this.vms = [])).push(vm)
|
||||
}
|
||||
|
||||
@ -89,7 +88,7 @@ export class Observer {
|
||||
* Remove an owner vm. This is called when the object is
|
||||
* swapped out as an instance's $data object.
|
||||
*/
|
||||
removeVm (vm: Vue) {
|
||||
removeVm (vm: Component) {
|
||||
remove(this.vms, vm)
|
||||
}
|
||||
}
|
||||
@ -109,11 +108,8 @@ function protoAugment (target, src: Object) {
|
||||
/**
|
||||
* Augment an target Object or Array by defining
|
||||
* hidden properties.
|
||||
*
|
||||
* @param {Object|Array} target
|
||||
* @param {Object} proto
|
||||
*/
|
||||
function copyAugment (target, src, keys) {
|
||||
function copyAugment (target: Object, src: Object, keys: Array<string>) {
|
||||
for (let i = 0, l = keys.length; i < l; i++) {
|
||||
const key = keys[i]
|
||||
def(target, key, src[key])
|
||||
@ -125,7 +121,7 @@ function copyAugment (target, src, keys) {
|
||||
* returns the new observer if successfully observed,
|
||||
* or the existing observer if the value already has one.
|
||||
*/
|
||||
export function observe (value: any, vm?: Vue): Observer | void {
|
||||
export function observe (value: any, vm?: Component): Observer | void {
|
||||
if (!isObject(value)) {
|
||||
return
|
||||
}
|
||||
@ -266,7 +262,7 @@ export function del (obj: Object, key: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function proxy (vm: Vue, key: string) {
|
||||
export function proxy (vm: Component, key: string) {
|
||||
if (!isReserved(key)) {
|
||||
Object.defineProperty(vm, key, {
|
||||
configurable: true,
|
||||
@ -282,7 +278,7 @@ export function proxy (vm: Vue, key: string) {
|
||||
}
|
||||
|
||||
// using Object type to avoid flow complaining
|
||||
export function unproxy (vm: Object, key: string) {
|
||||
export function unproxy (vm: Component, key: string) {
|
||||
if (!isReserved(key)) {
|
||||
delete vm[key]
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
import type Vue from '../instance/index'
|
||||
import Dep from './dep'
|
||||
import { queueWatcher } from './scheduler'
|
||||
import {
|
||||
@ -20,7 +19,7 @@ let prevTarget
|
||||
* This is used for both the $watch() api and directives.
|
||||
*/
|
||||
export default class Watcher {
|
||||
vm: Vue;
|
||||
vm: Component;
|
||||
expression: string;
|
||||
cb: Function;
|
||||
id: number;
|
||||
@ -37,7 +36,7 @@ export default class Watcher {
|
||||
value: any;
|
||||
|
||||
constructor (
|
||||
vm: Vue,
|
||||
vm: Component,
|
||||
expOrFn: string | Function,
|
||||
cb: Function,
|
||||
options?: Object = {}
|
||||
|
@ -69,7 +69,7 @@ function mergeData (to: Object, from: ?Object): Object {
|
||||
strats.data = function (
|
||||
parentVal: any,
|
||||
childVal: any,
|
||||
vm?: Vue
|
||||
vm?: Component
|
||||
): ?Function {
|
||||
if (!vm) {
|
||||
// in a Vue.extend merge, both should be functions
|
||||
@ -276,7 +276,7 @@ function guardDirectives (options: Object) {
|
||||
* Merge two option objects into a new one.
|
||||
* Core utility used in both instantiation and inheritance.
|
||||
*/
|
||||
export function mergeOptions (parent: Object, child: Object, vm?: Vue) {
|
||||
export function mergeOptions (parent: Object, child: Object, vm?: Component) {
|
||||
guardComponents(child)
|
||||
guardProps(child)
|
||||
guardDirectives(child)
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
import type Vue from '../instance/index'
|
||||
import { hasOwn, isObject, isPlainObject } from 'shared/util'
|
||||
import { observe, observerState } from '../observer/index'
|
||||
import { warn } from './debug'
|
||||
@ -12,7 +11,7 @@ type PropOptions = {
|
||||
validator: ?Function
|
||||
}
|
||||
|
||||
export function validateProp (vm: Vue, key: string, propsData: ?Object): any {
|
||||
export function validateProp (vm: Component, key: string, propsData: ?Object): any {
|
||||
if (!propsData) return
|
||||
const prop = vm.$options.props[key]
|
||||
const absent = hasOwn(propsData, key)
|
||||
@ -35,7 +34,7 @@ export function validateProp (vm: Vue, key: string, propsData: ?Object): any {
|
||||
/**
|
||||
* Get the default value of a prop.
|
||||
*/
|
||||
function getPropDefaultValue (vm: Vue, prop: PropOptions, name: string): any {
|
||||
function getPropDefaultValue (vm: Component, prop: PropOptions, name: string): any {
|
||||
// no default, return undefined
|
||||
if (!hasOwn(prop, 'default')) {
|
||||
// absent boolean value defaults to false
|
||||
@ -66,7 +65,7 @@ function assertProp (
|
||||
prop: PropOptions,
|
||||
name: string,
|
||||
value: any,
|
||||
vm: Vue,
|
||||
vm: Component,
|
||||
absent: boolean
|
||||
) {
|
||||
if (prop.required && absent) {
|
||||
|
@ -1,9 +1,9 @@
|
||||
/* @flow */
|
||||
|
||||
import Vue from './web-runtime'
|
||||
import config from 'core/config'
|
||||
import { warn, cached } from 'core/util/index'
|
||||
import { query } from 'web/util/index'
|
||||
import Vue from './web-runtime'
|
||||
import { compileToFunctions } from './web-compiler'
|
||||
|
||||
const idToTemplate = cached(id => query(id).innerHTML)
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
import type Vue from 'core/instance/index'
|
||||
import RenderStream from './render-stream'
|
||||
import { createRenderFunction } from './render'
|
||||
import { warn } from 'core/util/debug'
|
||||
@ -30,7 +29,7 @@ export function createRenderer ({
|
||||
|
||||
return {
|
||||
renderToString (
|
||||
component: Vue,
|
||||
component: Component,
|
||||
done: (err: ?Error, res: ?string) => any
|
||||
): void {
|
||||
let result = ''
|
||||
@ -58,7 +57,7 @@ export function createRenderer ({
|
||||
}
|
||||
},
|
||||
|
||||
renderToStream (component: Vue): RenderStream {
|
||||
renderToStream (component: Component): RenderStream {
|
||||
return new RenderStream((write, done) => {
|
||||
render(component, write, done)
|
||||
})
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
import type Vue from 'core/instance/index'
|
||||
import type VNode from 'core/vdom/vnode'
|
||||
import { createComponentInstanceForVnode } from 'core/vdom/create-component'
|
||||
|
||||
@ -82,7 +81,7 @@ export function createRenderFunction (
|
||||
return markup + '>'
|
||||
}
|
||||
|
||||
return function render (component: Vue, write: Function, done: Function) {
|
||||
return function render (component: Component, write: Function, done: Function) {
|
||||
renderNode(component._render(), write, done, true)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user