フロントエンドルーティングを実装するために実際には非常にシンプルですが、URLの性質の変化を監視していないし、次にルーティングルールに合致する、適切なページを表示し、リフレッシュする必要ことです。VUE-ルータ3人の警備員がありますアセンブリ内の排他的なガード、ガードをルーティング、グローバルガードされています。
ナビゲーションガード
- グローバルガード
EP:無着陸がない場合ページに入ろうとして設定されたグローバルガード、ログインページにリダイレクトされますがrouter.beforeEachを使用することができ、グローバルな事前ガードが登録しました
router.beforeEach((to,from,next) => {
console.log(to.meta)
// 判断是否登录
if (to.path === '/about' && !window.isLogin) {
next('/login?redirect='+to.path);
} else {
next();
}
})
复制代码
- 排他的なガードをルーティング
{
path: "/about",
name: "about",
meta: {requireLogin:true}, // meta 取值就是to.meta
beforeEnter(to,from,next) {
// 判断是否登录 路由独享守卫
if (!store.state.isLogin) {
next('/login?redirect='+to.path);
} else {
next();
}
},
component: () =>
import(/* webpackChunkName: "about" */ "./views/About.vue")
}
复制代码
グローバルガードと同じ効果
- アセンブリ内のガード
export default {
beforeRouteEnter(to, from, next) {}
beforeRouteUpdata(to, from, next) {}
beforeRouteLeave(to, from, next) {}
}
复制代码
完全なナビゲーション解決プロセス
- ナビゲーションがトリガされます。
- 通話中の構成要素の不活性化では、ガードを終了します。
- グローバルbeforeEachガードを呼び出します。
- コンポーネントの再利用でbeforeRouteUpdateガード(2.2以降)を呼び出します。
- 構成コールルーティングBeforeEnter。
- 非同期ルーティングコンポーネントを解決します。
- 内部のコンポーネントを起動されbeforeRouteEnterを呼び出します。
- グローバルbeforeResolveガード(2.5+)を呼び出します。
- ナビゲーションが確認されました。
- afterEachは、グローバルフックを呼び出します。
- DOMは更新をトリガ。
- コールバック関数の次のパスにbeforeRouteEnterガードを呼び出すことによって、良い例を作成します。
メタメタ情報ルート
EP:経路でdocument.titleを設定
{
path: '/customer/new',
name: 'NewCustomer',
meta: {title: '新增客户'},
component: () => import('@/Views/CustomerNew')
},
router.beforeEach(function (to, from, next) {
if (to.meta && to.meta.title) {
document.title = ((to.meta && to.meta.title))
}
next()
})
复制代码
ハッシュモード&&履歴モード
とき、ハッシュ値の変化の背後にある#www.test.com/#/は、ハッシュURLで、サーバーのデータにない要求は、ページをジャンプするURLのなhashchange事象の変化によって監視することができます。
履歴モードは、ハッシュURLよりも美しい新しいHTML5の機能であり、ソースコードの実装
アプリケーションページ
<router-link to="#/foo">foo</router-link> |
<router-link to="#/bar">bar</router-link>
复制代码
ルータの設定
const Foo = {
render() {
return <div>Foo</div>;
}
};
const Bar = {
render() {
return <div>Bar</div>;
}
};
export default new TRouter(Vue, {
routes: [
{
path: "/foo",
component: Foo
},
{
path: "/bar",
component: Bar
}
]
});
复制代码
ソースコードの実装
import Vue from "vue";
class TRouter {
constructor(Vue, options) {
this.$options = options;
this.routeMap = {}; // 全局的路由映射 key就是path(唯一的)
this.app = new Vue({ // 对vue的强依赖
data: {
current: "#/" // 当前路由
}
});
this.init();
this.createRouteMap(this.$options);
this.initComponent(Vue);
}
// 初始化 hashchange
init() {
// load事件在页面或某个资源加载成功时触发
window.addEventListener("load", this.onHashChange.bind(this), false);
// hashchange事件在 URL 的 hash 部分(即#号后面的部分,包括#号)发生变化时触发。
window.addEventListener("hashchange", this.onHashChange.bind(this), false);
}
createRouteMap(options) {
options.routes.forEach(item => {
this.routeMap[item.path] = item.component;
});
}
// 注册组件
initComponent(Vue) {
Vue.component("router-link", { // 全局注册
props: {
to: String // 去哪个地址
},
render: function (h) { // 传入函数 h 就是createElement
// <a :href="to"><slot></slot></a>
// 返回的是虚拟dom
return h("a", { attrs: { href: this.to } }, this.$slots.default);
}
});
const _this = this; // 全局this
Vue.component("router-view", { // 占位符
render(h) { // 根据当前路由发生变化 渲染当前组件所匹配的组件
var component = _this.routeMap[_this.app.current];
return h(component);
}
});
}
// 获取当前 hash 串
getHash() {
return window.location.hash.slice(1) || "/";
}
// 设置当前路径
onHashChange() { // 挂载的组件刷新
this.app.current = this.getHash(); // 获取最新hish赋值
console.log(this.app.current, 'this.app.current')
}
}
复制代码
概要
VUEのVUEルータは、単に、本質的に異なる内容に戻り、異なる経路によるパッケージの履歴と理解、または実現されてもよい、に強く依存します。
ます。https://juejin.im/post/5d0210036fb9a07eda03122aで再現