私はまだVue-Vueのインスタンス化を理解していません.
Vueの定義
トピックに直進し、
これが
以下の多くの
この文章は主に
すべてのすべてはは、 に記載されているように、
ここで、グローバルに登録されたコンポーネントは、,
親登録イベントが取得され、ある場合はサブコンポーネントに接続されます.
まとめ
この文章は主に
トピックに直進し、
Vue
は/core/instance/index.js
に定義される.import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'
function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options)
}
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
export default Vue
これが
Vue
の定義で、それは実は1つの構造関数で、ここで特筆すべきは、Vue
はES6 Class
の文法を使用していないで、Vue
の構造関数のprototype
を拡張することを通じて、javascript
の原型の設計を十分に利用してモジュール化を実現して、下の多くのmixin
がVue
の機能を拡張することを見ることができます.このようなコード設計は、読み取りとメンテナンスに非常に便利です.以下の多くの
__Mixin(Vue)
は、実際に例示化されたオブジェクトがこれらの機能を使用できるように、Vue.prototype
に方法を追加することである.この文章は主に
Vue
の実例化過程を述べる.すべてのすべては
new Vue(options)
から始まり、実際には上に見たthis._init(options)
を呼び出した._init
の定義を見てみましょう. Vue.prototype._init = function (options?: Object) {
const vm: Component = this
// a uid
vm._uid = uid++
let startTag, endTag
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
startTag = `vue-perf-start:${vm._uid}`
endTag = `vue-perf-end:${vm._uid}`
mark(startTag)
}
// a flag to avoid this being observed
vm._isVue = true
// merge options
if (options && options._isComponent) {
// optimize internal component instantiation
// since dynamic options merging is pretty slow, and none of the
// internal component options needs special treatment.
initInternalComponent(vm, options)
} else {
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
)
}
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production') {
initProxy(vm)
} else {
vm._renderProxy = vm
}
// expose real self
vm._self = vm
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, 'beforeCreate')
initInjections(vm) // resolve injections before data/props
initState(vm)
initProvide(vm) // resolve provide after data/props
callHook(vm, 'created')
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
vm._name = formatComponentName(vm, false)
mark(endTag)
measure(`vue ${vm._name} init`, startTag, endTag)
}
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}
vm
を現在の実行コンテキストとして定義し、すなわち、現在のnew
からのインスタンスまたはそのサブコンポーネントを指す.startTag endTag
性能に関連し、window.performance
打点により性能を試験した. // a flag to avoid this being observed
vm._isVue = true
Vue
のすべてのインスタンスは_isVue
としてマークされ、その役割は、インスタンスがset
またはdel
であることを回避することである.ポイントを引く!!!プロジェクトでVue.set(this, key, value) Vue.del(this, key, value)
を直接使用することはできません.そうしないと、エラーが発生します. if (options && options._isComponent) {
initInternalComponent(vm, options)
} else {
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
)
}
Vue
のマージポリシーは遅いので、内部コンポーネントを登録するときに特別な処理をする必要がないので、内部コンポーネントを直接初期化します.内部コンポーネントの識別は_isComponent
で、内部コンポーネントを作成する最初のステップでは、内部コンポーネントのoption._isComponent
をtrue
に設定します.次のコードを見てください:export function createComponentInstanceForVnode (vnode: any, parent: any,): Component {
const options: InternalComponentOptions = {
_isComponent: true,
_parentVnode: vnode,
parent
}
// ...
return new vnode.componentOptions.Ctor(options)
}
ここで、グローバルに登録されたコンポーネントは、
Vue.options.components
に登録されているが、サブコンポーネントの作成プロセスは、vm.constructor.options
を自分の$options
に拡張し、グローバルに登録されたコンポーネントが任意のコンポーネントで使用できる理由である.mergeOptions
という記事がある時にすでに言及していますが、initGlobalAPI
はその時に定義されています.Vue.options
はresolveConstructorOptions
の場合、new Vue
に直接戻り、サブクラスが拡張されていれば、再び複雑な合併を行った後、新しいVue.options
に戻ります.最後に、パラメータを新しいoptions
とマージします.options
ライフサイクルに関連する属性を初期化する限り、この方法は比較的簡単です.initLifecycle
export function initEvents (vm: Component) {
vm._events = Object.create(null)
vm._hasHookEvent = false
// init parent attached events
const listeners = vm.$options._parentListeners
if (listeners) {
updateComponentListeners(vm, listeners)
}
}
export function updateComponentListeners (
vm: Component,
listeners: Object,
oldListeners: ?Object
) {
target = vm
updateListeners(listeners, oldListeners || {}, add, remove, createOnceHandler, vm)
target = undefined
}
// add
function add (event, fn) {
target.$on(event, fn)
}
親登録イベントが取得され、ある場合はサブコンポーネントに接続されます.
initEvents
のカスタムコンポーネントを使用すると、サブコンポーネント内でv-on
のイベントを介して親コンポーネントに通知されます.このシーンは、親コンポーネントイベントが現在のコンポーネントに定義されている問題を理解するのに役立ちます.ここでの具体的な手順は、コンポーネント内で$emit
を使用してイベントが登録されている場合、v-on
、すなわちadd
によってイベントが$on
にロードされ、サブコンポーネントvm._events
のときにコールバックが完了することである.このうち$emit
イベントは、イベントが実行された後、once
を呼び出して登録時間を削除する.$off
ここでもいくつかの属性に対する付与値であり、その中で重要なのは: vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)
// normalization is always applied for the public version, used in
// user-written render functions.
vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)
initRender
が作成され、レンダリングの詳細については説明します.vnode
callHook(vm, 'beforeCreate')
initState
callHook(vm, 'created')
およびcallHook(vm, 'beforeCreate')
は、多くの説明を必要とせずに、callHook(vm, 'created')
のライフサイクル関数を呼び出す.Vue
にはinitState
、props
などが初期化されており、ここではdata
のコア部分であり、データハイジャックによって応答式原理が実現されている.Vue
が応答するときの原理は詳細に説明されます.実際には、Vue
の場合、beforeCreate
を使用してインスタンスのデータを取得できない理由が理解されていますが、this
で取得できるのは、created
の場合、beforeCreate
がまだinitState
になっていないことです.inject/provide
はコンポーネント通信を実現する新しい方式であり、親子、子孫などの通信方式を実現することができる.まとめ
この文章は主に
new Vue
の過程を述べて、異なる機能が異なる関数に分割されて実行されることを見ることができて、筋道の論理ははっきりしていて、主線は明確で、初期化の最後に、el
の属性があれば、vm.$mount
の方法を呼び出してマウントして、マウントの目的はテンプレートを最終的なDOM
にレンダリングすることです.