vue 手写一个vue-router

    科技2022-07-21  97

    实现效果如下:

    1. 准备好环境

    使用 vue/cil 初始化项目配置:

    npm install -g @vue/cli //全局安装@vue/cli vue create demo-vue //创建项目

    yarn add vue-router 安装vue-router创建一个router文件夹并使用:

    2. 实现目的

    router/index.js内容如下:(我们的目的将引入自写的vue-router实现vue路由跳转功能)

    import vue from 'vue' //import vueRouter from 'vue-router' //使用官方 vue-router 插件 import vueRouter from './my-vue-router' //使用我们直接实现的 vue-router 插件 vue.use(vueRouter) //此时执行 my-vue-router 内 install 方法 const routes = [ { path: '/', redrect: '/a' }, { path: '/a', name: 'a', component: () => import('../views/a.vue') }, { path: '/b', name: 'b', component: () => import('../views/b.vue') } ] const router = new vueRouter({ mode: 'hash', //哈希路由 routes }) export default router //main.js 引入实例化的 router 添加至 this.$options.router 中

    3. 实现原理

    router/my-vue-router.js 实现过程如下:

    let Vue //声明一个变量用来存储install内接收的vue实例 给 constructor 内调用 class vueRouter { constructor(options) { this.$options = options //用于通过全局 this.$options.router.$options 获取 const initail = window.location.hash.slice(1) || '/' Vue.util.defineReactive(this, 'current', initail) //监听数据响应式渲染页面 window.addEventListener('hashchange', () => { //监听哈希路由变化 this.current = window.location.hash.slice(1) //改变触发 render 渲染页面 }) } push() { console.log("跳转页面"); } } vueRouter.install = function(_vue) { Vue = _vue Vue.mixin({ beforeCreate() { if (this.$options.router) { Vue.prototype.$router = this.$options.router //将全局数据注入组件 } } }) Vue.component('router-link', { //注册全局 router-link 组件 props: { to: { type: String, required: true } }, render(h) { return h( 'a', { attrs: { href: '#' + this.to } }, this.$slots.default ) } }) Vue.component('router-view', { //注册全局 router-view 组件 render(h) { console.log(" this.$router", this.$router); const route = this.$router.$options.routes.find((route) => { return route.path == this.$router.current }) return h(route.component) //将组件渲染返回 } }) } export default vueRouter

    3. 使用手写vue-router:

    a.vue 与 b.vue 可任意写

    <template> <div id="app"> <router-link to="/a">aaa</router-link> | <router-link to="/b">bbb</router-link> <router-view></router-view> </div> </template> <script> export default { name: 'App' } </script>
    Processed: 0.011, SQL: 8