Pré-conhecimento
Dois modos de roteamento front-end
O conteúdo por trás de # no URL do modo Hash é usado como o endereço do caminho.
Ouça o evento HashChange.
Encontre o componente correspondente com base no endereço de roteamento atual e renderize novamente- Modo de histórico
Altere a barra de endereço através do método history.pushState (),
ouça os eventos popstate,
encontre o componente correspondente com base no endereço de roteamento atual e renderize novamente
Preparação de roteamento manuscrito
Crie um novo projeto vue sem vue-router
Crie um novo arquivo relacionado ao roteador no projeto
- Crie uma nova pasta de rota e crie um novo index.js na pasta para armazenar regras de roteamento
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
-
Crie uma nova pasta vuerouter e crie um novo index.js na pasta para armazenar o código do roteador escrito à mão
-
Não se esqueça de citar o roteador que escrevemos em 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')
Comece a escrever à mão Vue-Router
Em primeiro lugar, é necessário esclarecer o que fazer manuscrito Vue-roteador. A figura a seguir é um diagrama de classes do Vue-roteador, que registra em detalhes quais atributos e métodos VueRouter precisa
opções: registrar o objeto passado no construtor (existem regras de roteamento neste objeto)
routeMap: é um objeto usado para registrar a correspondência entre o endereço de roteamento e o componente, as regras de roteamento serão analisadas no routeMap nos
dados futuros : é um objeto, há um atributo current, que é usado para registrar o endereço de roteamento atual.Aqui, os dados são usados para implementar um objeto responsivo.
implementação do método de instalação
Por meio de _ no diagrama de classe, você pode descobrir que instalar é um método estático
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
},
})
}
}
Implementação do construtor
constructor(options){
this.options = options
this.routerMap = {
} // 用于存储解析的router对象
this.data = _Vue.observable({
current:'/'
})
// this.init()
}
Desta forma, os atributos relevantes no diagrama de classes são realizados
Implementação do método CreateRouterMap
A função deste método é converter as regras de roteamento passadas no construtor na forma de pares chave-valor e armazená-las no routeMap mencionado acima
//遍历所有的路由规则,解析路由规则变为键值对的形式,存储到routermap里
createRouterMap(){
this.options.routes.forEach(route =>{
this.routerMap[route.path] = route.component
})
}
Implementação do método 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)
},
})
}
Implementação do método initEvent
initEvent(){
window.addEventListener('popstate',()=>{
this.data.current = window.location.pathname
})
}
Este método é para carregar e renderizar componentes ao voltar e avançar no navegador
Código de roteamento escrito à mão completo
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
})
}
}
Referência:
Lagou Education