vue3 实现简易的router

实现了个简易的router,只做了路由切换支持hashhistory模式
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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值