实现了个简易的router,只做了路由切换支持hash
和history
模式
index.js 代码
import {ref,inject} from 'vue'
import RouterView from "./RouterView.vue"
import RouterLink from "./RouterLink.vue"
const ROUTER_KEY = '__router__'
function createRouter(options){
return new Router(options)
}
function useRouter(){
return inject(ROUTER_KEY)
}
function createWebHistory(){
function binEvents(fn){
window.addEventListener('popstate',fn)
}
return{
binEvents,
type: 'History',
url: ()=>window.history.state?window.history.state.url: '/'
}
}
function createWebHashHistory(){
function binEvents(fn){
window.addEventListener('hashchange',fn)
}
return{
binEvents,
type: 'Hash',
url: ()=>window.location.hash.slice(1) || '/'
}
}
class Router{
constructor(options){
this.history = options.history
this.routes = options.routes
this.current = ref(this.history.url())
this.history.binEvents(()=>{
this.current.value = this.history.url()
})
}
install(app){
app.provide(ROUTER_KEY,this)
.component("router-link",RouterLink)
.component("router-view",RouterView)
}
}
export {createRouter,createWebHashHistory,createWebHistory,useRouter}
RouterView.vue 代码
<template>
<component :is="comp"></component>
</template>
<script setup>
import { computed } from "vue";
import { useRouter } from "./index";
let router = useRouter()
const comp = computed(()=>{
const route = router.routes.find((item)=>{
return item.path == router.current.value
})
return route?route.component : null
})
</script>
RouterLink.vue 代码
<template>
<a @click="switchUrl">
<slot />
</a>
</template>
<script setup>
import { defineProps } from "vue";
import { useRouter } from "./index";
let router = useRouter();
const props = defineProps({
to: { type: String, required: true },
});
function switchUrl() {
const routes = router.routes.find((item) => {
return item.path == props.to;
});
switch (router.history.type) {
case "Hash":
window.location.href = window.location.origin + "/#" + props.to;
break;
case "History":
window.history.pushState(
{ url: props.to, name: routes.name },
routes.name,
props.to
);
router.current.value = props.to;
break;
}
}
</script>
路由的使用:
import {
createRouter,
createWebHashHistory,
createWebHistory,
} from './grouter/index'
import Home from '../pages/home.vue'
import About from '../pages/about.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
}
]
const router = createRouter({
history: createWebHistory(),
routes: routes
})
export default router
App.vue
<template>
<div>
<router-link to="/">首页</router-link> |
<router-link to="/about">关于</router-link>
</div>
<router-view></router-view>
</template>
main.js
createApp(App).use(router)