ユーザーがWebページにアクセスしたときにアプリケーションバンドル全体がダウンロードされないように、webpackのコード分割機能を使用してアプリを複数のチャンクに分割しました。
一部のルートに必要なチャンクはかなり大きくなる可能性があり、ダウンロードにかなりの時間がかかる場合があります。これは問題ありませんが、ユーザーが内部リンクをクリックしたときにページが実際に読み込まれていることを認識していないため、読み込みアニメーションなどを表示する必要があります。
私のルーターは次のように構成されています。
[
{
path: '/',
component: () => import(/* webpackChunkName: 'landing' */ './landing.vue'),
},
{
path: '/foo',
component: () => import(/* webpackChunkName: 'main' */ './foo.vue'),
},
{
path: '/bar',
component: () => import(/* webpackChunkName: 'main' */ './bar.vue'),
},
]
高度な非同期コンポーネント Vue.jsガイドでは、コンポーネントの解決中に特定の「ロード」コンポーネントを表示する方法を示しています-これはまさに私が必要なものですが、それはまた言っています:
Vue-routerでルートコンポーネントとして使用する場合、ルートナビゲーションが発生する前に非同期コンポーネントが事前に解決されるため、これらのプロパティは無視されることに注意してください。
Vue-routerでこれをどのように達成できますか?これが不可能な場合、遅延ロードされたコンポーネントは、ユーザーに悪いエクスペリエンスを提供するため、ほとんど役に立たないでしょう。
ナビゲーションガードを使用して、読み込みコンポーネントを表示/非表示にする読み込み状態を有効/無効にすることができます。
「nprogress」のようなものを使用したい場合は、次のようにします。
http://jsfiddle.net/xgrjzsup/2669/
const router = new VueRouter({
routes
})
router.beforeEach((to, from, next) => {
NProgress.start()
next()
})
router.afterEach(() => {
NProgress.done()
})
または、インプレースを表示したい場合:
http://jsfiddle.net/h4x8ebye/1/
Vue.component('loading',{ template: '<div>Loading!</div>'})
const router = new VueRouter({
routes
})
const app = new Vue({
data: { loading: false },
router
}).$mount('#app')
router.beforeEach((to, from, next) => {
app.loading = true
next()
})
router.afterEach((to, from, next) => {
setTimeout(() => app.loading = false, 1500) // timeout for demo purposes
next()
})
次に、テンプレートで:
<loading v-if="$root.loading"></loading>
<router-view v-else></router-view>
また、ロード状態に$ rootコンポーネントを使用する代わりに、非常に小さなコンポーネントに簡単に組み込むことができます。
それが価値があるものについては、私が自分の状況のためにやったことを共有します。
Vuexを使用しているので、すべてのコンポーネントがアクセスできるアプリ全体の「読み込み」状態を簡単に作成できましたが、この状態を共有したい任意のメカニズムを使用できます。
簡略化すると、次のように機能します。
_function componentLoader(store, fn) {
return () => {
// (Vuex) Loading begins now
store.commit('LOADING_BAR_TASK_BEGIN');
// (Vuex) Call when loading is done
const done = () => store.commit('LOADING_BAR_TASK_END');
const promise = fn();
promise.then(done, done);
return promise;
};
}
function createRoutes(store) {
const load = fn => componentLoader(store, fn);
return [
{
path: '/foo',
component: load(() => import('./components/foo.vue')),
},
{
path: '/bar',
component: load(() => import('./components/bar.vue')),
},
];
}
_
したがって、すべての_() => import()
_を、ロード状態の設定を処理するload()
関数でラップするだけです。読み込みは、ルーター固有のbefore/afterフックに依存する代わりに、promiseを直接観察することにより決定されます。