事前知識
フロントエンドルーティングの2つのモード
- ハッシュモード
URLの#の後ろのコンテンツがパスアドレスとして使用されます
。HashChangeイベントをリッスンします。
現在のルーティングアドレスに基づいて対応するコンポーネントを見つけ、再レンダリングします。 - 履歴モード
history.pushState()メソッドを使用してアドレスバーを変更し、
ポップステートイベントをリッスン
し、現在のルーティングアドレスに基づいて対応するコンポーネントを見つけ、再レンダリングします。
手書きルーティングの準備
vue-routerなしで新しいvueプロジェクトを作成する
プロジェクトに新しいルーター関連ファイルを作成します
- 新しいルートフォルダを作成し、そのフォルダの下に新しいindex.jsを作成して、ルーティングルールを保存します
import Vue from 'vue'
import VueRouter from '../vuerouter'
//从我们自己的router中导入VueRouter
import Index from '../components/Index.vue'
Vue.use(VueRouter)
const routes = [
{
path:'/',
name:'Index',
component : Index
},
{
path:'/about',
name:'about',
component: ()=> import('@/views/about.vue')
},
{
path:'/home',
name:'home',
component: ()=> import('@/views/home.vue')
},
]
const router = new VueRouter({
mode:'history',
base: process.env.BASE_URL,
routes
})
export default router
-
新しいvuerouterフォルダーを作成し、フォルダーの下に新しいindex.jsを作成して、手書きのルーターコードを保存します。
-
main.jsで作成したルーターを引用することを忘れないでください
import Vue from 'vue'
import App from './App.vue'
import router from './route'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
手書きのVue-Routerを開始します
まず、Vue-routerを手書きして何をすべきかを明確にする必要があります。次の図は、VueRouterに必要な属性とメソッドを詳細に記録したVue-routerのクラス図です。
オプション:コンストラクターで渡されたオブジェクトを記録します(このオブジェクトにはルーティングルールがあります)
routeMap:ルーティングアドレスとコンポーネント間の対応を記録するために使用されるオブジェクトです。ルーティングルールは、将来の
データでrouteMapに解析されます。 :はオブジェクトです。現在のルーティングアドレスを記録するために使用される属性currentがあります。ここでは、データは応答オブジェクトを実装するために使用されます。
インストールメソッドの実装
クラス図の_から、インストールが静的メソッドであることがわかります。
let _Vue = null
export default class VueRouter {
static install (Vue) {
//判断当前插件是否被安装
if(VueRouter.install.installed){
return;
}
VueRouter.install.installed = true
// 把vue构造函数记录到全局变量
_Vue = Vue
// 把创建vue实例的时候传入的router对象注入到Vue实例上
//混入 mixed
_Vue.mixin({
beforeCreate() {
if(this.$options.router)
_Vue.prototype.$router = this.$options.router
},
})
}
}
コンストラクターの実装
constructor(options){
this.options = options
this.routerMap = {
} // 用于存储解析的router对象
this.data = _Vue.observable({
current:'/'
})
// this.init()
}
このようにして、クラス図の関連する属性が実現されます
CreateRouterMapメソッドの実装
このメソッドの機能は、コンストラクターに渡されたルーティングルールをキーと値のペアの形式に変換し、上記のrouteMapに格納することです。
//遍历所有的路由规则,解析路由规则变为键值对的形式,存储到routermap里
createRouterMap(){
this.options.routes.forEach(route =>{
this.routerMap[route.path] = route.component
})
}
initComponentsメソッドの実装
initComponents (Vue) {
Vue.component('router-link',{
props:{
to:String
//接收外部传入的to
},
// template:'<a :href="to"><slot></slot></a>'
render (h) {
return h('a',{
attrs:{
href:this.to
},
on:{
click:this.clickHandler
}
},[this.$slots.default])
},
methods: {
clickHandler(e){
history.pushState({
},'',this.to)
this.$router.data.current = this.to
e.preventDefault();
}
},
})
const _this = this
Vue.component('router-view', {
render(h) {
const component = _this.routerMap[_this.data.current]
return h(component)
},
})
}
initEventメソッドの実装
initEvent(){
window.addEventListener('popstate',()=>{
this.data.current = window.location.pathname
})
}
この方法は、ブラウザで前後に移動するときにコンポーネントをロードしてレンダリングする方法です。
完全な手書きのルーティングコード
let _Vue = null
export default class VueRouter {
static install (Vue) {
//判断当前插件是否被安装
if(VueRouter.install.installed){
return;
}
VueRouter.install.installed = true
// 把vue构造函数记录到全局变量
_Vue = Vue
// 把创建vue实例的时候传入的router对象注入到Vue实例上
//混入 mixed
_Vue.mixin({
beforeCreate() {
if(this.$options.router)
_Vue.prototype.$router = this.$options.router
// this.$options.router.init()
},
})
}
constructor(options){
this.options = options
this.routerMap = {
} // 用于存储解析的router对象
this.data = _Vue.observable({
current:'/'
})
this.init()
}
init(){
this.createRouterMap()
this.initComponents(_Vue)
this.initEvent()
}
//遍历所有的路由规则,解析路由规则变为键值对的形式,存储到routermap里
createRouterMap(){
this.options.routes.forEach(route =>{
this.routerMap[route.path] = route.component
})
}
initComponents (Vue) {
Vue.component('router-link',{
props:{
to:String
},
// template:'<a :href="to"><slot></slot></a>'
render (h) {
return h('a',{
attrs:{
href:this.to
},
on:{
click:this.clickHandler
}
},[this.$slots.default])
},
methods: {
clickHandler(e){
history.pushState({
},'',this.to)
this.$router.data.current = this.to
e.preventDefault();
}
},
})
const _this = this
Vue.component('router-view', {
render(h) {
const component = _this.routerMap[_this.data.current]
return h(component)
},
})
}
initEvent(){
window.addEventListener('popstate',()=>{
this.data.current = window.location.pathname
})
}
}
参照:
Lagou Education