vue-routerソース解析(二)プラグイン実装
6312 ワード
vue-routerプラグイン方式の実現
vue-routerはプラグインとしてvueに統合されています.
vue-routerを使用する場合、最初の部分はプラグイン
プラグインについてはvueの公式ドキュメントを参照できます
プラグインの開発方法に重点を置いています
プラグインの開発方法グローバルメソッドまたは属性 を追加グローバルリソースの追加:コマンド/フィルタ/遷移など、 グローバルmixinメソッドでコンポーネントオプションを追加します. Vueインスタンスメソッドを追加することは、 は、上述の1つまたは複数の機能 を同時に提供する独自のAPIを提供するライブラリである.
vue-routerのinstall
まず、エントリファイル
したがって、具体的な実装は
インストール実装
Installは比較的論理的に簡単です.主に以下の部分を行いました.
重複インストールの防止
グローバル変数を1つ使用して、1回のみインストールできることを確認します.
グローバル
注目すべきは
どこから来たのか疑問に思うかもしれません.
変数をプロトタイプにマウント
次の形式で変数を定義します.私たちがよく使う
ここを通る
読み取り専用、変更不可
グローバルコンポーネントの登録
最後に
その他
シリーズ記事リスト個人ブログ
vue-routerはプラグインとしてvueに統合されています.
vue-routerを使用する場合、最初の部分はプラグイン
Vue.use(VueRouter);
をインストールすることです.プラグインについてはvueの公式ドキュメントを参照できます
プラグインの開発方法に重点を置いています
プラグインの開発方法
Vue.js
は、プラグインに開示された方法install
があるべきであることを要求する.この方法の第1のパラメータはVue
コンストラクタであり、第2のパラメータはオプションのオプションオブジェクトである.install
の方法では、関連する処理を行うことができます.Vue.prototype
に追加することによって実現される.MyPlugin.install = function (Vue, options) {
// 1.
Vue.myGlobalMethod = function () {
// ...
}
// 2.
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// ...
}
...
})
// 3.
Vue.mixin({
created: function () {
// ...
}
...
})
// 4.
Vue.prototype.$myMethod = function (methodOptions) {
// ...
}
}
vue.js
プラグインの実装の考え方をざっと理解した後、vue-router
の処理を見てみましょう.vue-routerのinstall
まず、エントリファイル
src/index.js
を参照してください.import { install } from './install';
// ...more
VueRouter.install = install;
したがって、具体的な実装は
install
にある.次に具体的に何をしたのか見てみましょう.インストール実装
Installは比較的論理的に簡単です.主に以下の部分を行いました.
重複インストールの防止
グローバル変数を1つ使用して、1回のみインストールできることを確認します.
//
export let _Vue;
export function install(Vue) {
//
if (install.installed && _Vue === Vue) return;
install.installed = true;
// ...more
}
グローバル
mixin
によるライフサイクルの注入処理export function install(Vue) {
// ...more
const isDef = v => v !== undefined;
//
const registerInstance = (vm, callVal) => {
let i = vm.$options._parentVnode;
if (
isDef(i) &&
isDef((i = i.data)) &&
isDef((i = i.registerRouteInstance))
) {
i(vm, callVal);
}
};
//
Vue.mixin({
beforeCreate() {
if (isDef(this.$options.router)) {
// router ,
this._routerRoot = this;
this._router = this.$options.router;
this._router.init(this);
Vue.util.defineReactive(
this,
'_route',
this._router.history.current
);
} else {
this._routerRoot =
(this.$parent && this.$parent._routerRoot) || this;
}
//
registerInstance(this, this);
},
destroyed() {
//
registerInstance(this);
}
});
// ...more
}
mixin
を用いて、beforeCreate
およびdestroyed
を例に追加した.インスタンスを登録および破棄します.注目すべきは
registerInstance
関数のvm.$options._parentVnode.data.registerRouteInstance;
どこから来たのか疑問に思うかもしれません.
./src/components/view.js
,route-view
コンポーネントのrenderメソッドで定義されています.主に登録と廃棄の実例に用いられ、具体的には後でお話しします.変数をプロトタイプにマウント
次の形式で変数を定義します.私たちがよく使う
this.$router ,this.$route
は、ここで定義されています.//
Object.defineProperty(Vue.prototype, '$router', {
get() {
return this._routerRoot._router;
}
});
//
Object.defineProperty(Vue.prototype, '$route', {
get() {
return this._routerRoot._route;
}
});
ここを通る
Object.defineProperty
定義get
を使用せずに実装Vue.prototype.$router = this.this._routerRoot._router
. 読み取り専用、変更不可
グローバルコンポーネントの登録
import View from './components/view';
import Link from './components/link';
export function install(Vue) {
// ...more
//
Vue.component('RouterView', View);
Vue.component('RouterLink', Link);
// ...more
}
最後に
install.js
の完全なコードを添付import View from './components/view';
import Link from './components/link';
export let _Vue;
//
export function install(Vue) {
//
if (install.installed && _Vue === Vue) return;
install.installed = true;
_Vue = Vue;
const isDef = v => v !== undefined;
//
const registerInstance = (vm, callVal) => {
let i = vm.$options._parentVnode;
if (
isDef(i) &&
isDef((i = i.data)) &&
isDef((i = i.registerRouteInstance))
) {
i(vm, callVal);
}
};
//
Vue.mixin({
beforeCreate() {
if (isDef(this.$options.router)) {
// router ,
this._routerRoot = this;
this._router = this.$options.router;
this._router.init(this);
Vue.util.defineReactive(
this,
'_route',
this._router.history.current
);
} else {
this._routerRoot =
(this.$parent && this.$parent._routerRoot) || this;
}
//
registerInstance(this, this);
},
destroyed() {
registerInstance(this);
}
});
//
Object.defineProperty(Vue.prototype, '$router', {
get() {
return this._routerRoot._router;
}
});
//
Object.defineProperty(Vue.prototype, '$route', {
get() {
return this._routerRoot._route;
}
});
//
Vue.component('RouterView', View);
Vue.component('RouterLink', Link);
//
const strats = Vue.config.optionMergeStrategies;
// use the same hook merging strategy for route hooks
strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate =
strats.created;
}
その他
シリーズ記事リスト個人ブログ