前言
书接上回,我们实现了动态组件<component :is="component"></component>动态组件但是页面内容并没有实现,本文将完全实现router-view.
页面展示实现
我们使用hashchange方法获得Router对象,给对象中的url添加一个ref当url的值发生改变时,router-view中的计算属性computed就会重新计算值。
// 在任何地方只要使用useRouter就可以拿到router对象
const useRouter = () => {
return
}
const createWebHashHistory = () =>{//控制history实例化对象
// 给我们返回的是hisotry对象
// 那么craeteWebHashHistory方法就是返回一个url
function bindEvents(fn){
window.addEventListener('hashchange',fn)
}
return {
// 通过window拿到location地址 并且删除第一个`#` 如果没有那就是/
url:window.location.hash.slice(1) || '/',
bindEvents
}
}
class Router {
// 添加一个构造方法
constructor(options){
this.history = options.history
this.routes = options.routes
console.log(options,'////');
// 当前的url 状态 它是router-view中 component计算属性的依赖
this.current = ref(this.history.url)
this.history.bindEvents(()=>{
//内部的this 指向router
// 点击时自动更新当前的url
this.current.value = window.location.hash.slice(1)
console.log(this.current.value,'////');
})
}
我们定义一个bindEvents(fn)函数监听事件,当我们点击时,就会触发函数fn.我们提供一个useRouter方法,当我们调用函数,我们可以拿到router实例对象 也就是return new Router(options).监听事件的触发,我们需要对router的url实现自动更新。
我们切换页面时,url也会更新成相应页面的url.
我们的useRoute是需要向外全局提供的,所以我们便可以使用app.provide(KEY,router)第二个参数是我们想要全局共享的对象 ,可以将对象挂载在app上,provide是向任何组件提供,这个KEY就可以与inject()方法配合使用。
// VueRouter 封装在这里
import { ref,inject} from 'vue';
import RouterLink from './RouterLink.vue'
import RouterView from './RouterView.vue'
const ROUTER_KEY = '__router__'
// 提供一个useRouter方法
// 在任何地方只要使用useRouter就可以拿到router对象
const useRouter = () => {
// 当我们调用函数,我们可以拿到router实例对象 也就是return new Router(options)
return inject(ROUTER_KEY)
}
const createRouter = (options) =>{//控制Router实例化对象
return new Router(options)
}
// 返回一个hash的路由对象
// 路由对象由 url
// hashchange 传一个fn 触发时,fn会作为时间处理函数
const createWebHashHistory = () =>{//控制history实例化对象
// 给我们返回的是hisotry对象
// 那么craeteWebHashHistory方法就是返回一个url
function bindEvents(fn){
window.addEventListener('hashchange',fn)
}
return {
// 通过window拿到location地址 并且删除第一个`#` 如果没有那就是/
url:window.location.hash.slice(1) || '/',
bindEvents
}
}
class Router {
// 添加一个构造方法
constructor(options){
this.history = options.history
this.routes = options.routes
console.log(options,'////');
// 当前的url 状态 它是router-view中 component计算属性的依赖
this.current = ref(this.history.url)
this.history.bindEvents(()=>{
//内部的this 指向router
// 点击时自动更新当前的url
this.current.value = window.location.hash.slice(1)
console.log(this.current.value,'////');
})
}
// 提供一个install方法
install(app){
console.log(app);
// console.log('vue 要对接vue-router');
// 完成全局组件的声明
app.provide(ROUTER_KEY,this)//谁都可以使用,向外提供router对象 全局
app.component('router-link',RouterLink)
app.component('router-view',RouterView)
}
}
export {
createRouter,
createWebHashHistory,
useRouter
}
这个时候我们回到RouterView.vue中去处理一些数据
这里我们打印
router对象,原本我们写(route) => route.path === router.url但是对象中是不存在url的,我们检查对象中的值,current.value才是代表的地址,所以这里的判断语句我们写成
(route) => route.path === router.current.value.
最后在App.vue中加上<router-view/>就可以实现页面展示了。