vue中的vue-router的应用以及创建简易的router

(一)vue中的vue-router:

1. 安装vue-router:一般脚手架自带安装好了vue-router。

2. vue项目中引入和使用vue-router:更详细的使用参考:https://blog.csdn.net/qq_42231156/article/details/82949962

//在router.js文件中配置路由
import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router);   //vue中挂载vue-router插件

const router=new Router({
    mode:'history',   //模式包括hash、history、abstract
    base:process.env.BASE_URL,   //设置访问地址的域名,根据开发环境和正式环境不同自动配置
    routes:[
        {
            path:'/home',
            name:'home',
            props:true,   //表示允许组件props:{}中接受name参数值,然后可以直接渲染在页面{{name}}

            alias:'/home_page',//为路由取别名,即访问"/home_page"和访问"/home"和通过name:"home",访问的效果是一样的
            meta:[auth:true],  //是否开启路由权限校验,在路由守卫中,to.meta.auth && isLogin 即需要登录,且已经登录才会跳转路由
            components:()=>import('./view/home.vue')    //路由按需引入,按需加载,避免一次性加载过多的页面。
            beforeEnter(from,to,next){  //独享路由守卫

            },
            children:[   //嵌套子路由
                {
                    path:'detail:id',  // 相当于/home/detail:id,{{$route.params.id}}或者如果props:true时,可以在组件中通过props:{id:{type:String,default:""}}取得参数值
                    name:'detail',
                    components:()=>import('./view/detail.vue') 
                }
                
            ]
        }
    ]
})

//1. 后端返回登录人权限(超级管理员,普通管理员...)前端配置路由权限哪些可以跳转,哪些页面不能跳转。
//2. 后端直接返登录人可以返回跳转页面的权限页面列表,前端映射到响应的权限页面,用户只能登录后端返回的权限页面。

router.beforeEach((to,form,next)=>{ //路由全局守卫,已经登录就跳转要去的路由,没有登录就跳转登录页面
    to.meta.auth && localstorage.getItem('isLogin')?next():next('/login');
})  
router.beforeResolve((to,form,next)=>{})  //路由全局守卫
router.afterEach((to,form)=>{})  //路由全局守卫
export default router



//在main.js文件中配置router
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

3. vue-router中的路由守卫:包括全局守卫,独享守卫,组件内守卫。

(二)封装简易的ARouter.js:

原理:声明一个ARouter类挂载一个install方法,作为插件被vue使用(即Vue.use(ARouter))时,即执行ARouter类的install方法时将Vue作为参数传递进install方法中,挂载Vue全局混合Vue.mixins()(即所有vue组件执行时都会先执行混合),即在每个组件创建之前,查看该组件是否有this.$option.router,即是否是根组件,只有根组件才会有this.$option.router,在根组件时将路由实例挂载在vue全局上,也就是每个组件都可以调用$router,并执行ARouter类的init()初始化方法(即执行监听url的变化,配置路由的解析,.实现全局组件(router-link和router-view))。具体代码如下:

注意:简易封装的ARouter不能实现路由嵌套(存在无限嵌套循环),只考虑有hash的情况。

1. 创建一个ARouter.js文件:

//新建一个ARouter.js文件,封装简易的router


let Vue;

class ARouter{ //实现简单的vue-router
  static install(_vue){ // 这里Vue.use(ARouter)时执行install(),install里面的this指向Vue实例
      Vue=_vue;
      Vue.mixin({ //Vue的全局混合   
        beforeCreate(){      
            if(this.$option.router){  //仅仅在根组件的创建前声明周期上执行一次混合
                 Vue.prototype.$router=this.$option.router;   //在vue上挂载$router,实现在任何组件中都可以使用$router
                 this.$option.router.init();  //这里的this指的是new Vue() 而不是 ARouter的实例化
            }
              
        },    
  })
}
  constructor(options){ 
    this.$option=options;   //这里的this指的是ARouter实例
    this.routerMap={};  //用于存放配置的路由解析,即将routes数组,转换为对象映射
    this.app=new Vue({  //数据响应式路由
      data:{
        current:'/'   //当前路径的根路径,当这个值变化时,可以动态的让(router-link和router-view)组件重新渲染
      }
    })
  }
  init(){ //路由初始化时执行:
    this.bindEvents(); //1.监听url的变化
    this.createRouteMap(); //2.配置路由的解析
    this.initComponent(); //3.实现全局组件(router-link和router-view)
  }
  bindEvents(){
    window.addEventListener('load',this,onHashChange.bind(this),false);  //页面加载完成时执行,为了保持onHashChange函数里面的this保持是ARouter实例而不是window,所有需要bind(this)
    window.addEventListener('hashchange',this.onHashChange.bind(this),false); //当URL的片段标识符更改时,将触发hashchange事件(跟在#符号后面的URL部分,包括#符号)
  }
  onHashChange(e){  //e是路由变化时的对象
    let hash=window.location.hash.slice(1) || "/"
    let router=this.routerMap[hash]; //路由变化之后的的路由对象(但是还没有跳转)如:
                             //{path:"home",component: Home,beforeEnter(from,to,next){})}
    let fromPath,toPath;
    if(e.newURL){
        fromPath=e.oldURL.split("#")[1]
        toPath=e.newURL.split("#")[1]
    }else{
        fromPath='';
        toPath=hash;
    }
    if(router.beforeEnter){
        router.beforeEnter(fromPath,toPath,()=>{
            this.app.current=hash; //此时才执行跳转路由,因为new Vue的current值改变。重新渲染
        })
    }else{
        this.app.current=hash;
    }
     
                                                            //window.location.hash='#/down?id=1',indow.location.hash.slice(1)='/down?id=1',思考:当页面url不是hash模式的处理?
  }
  createRouteMap(){  //new ARouter({routes:[]})里面的routes
   this.$option.routes.forEach((item)=>{
    this.routerMap[item.path]=item;  //形成键值对 {'/':Home,'/about':About}之类的页面路由path和页面一一对应起来
   })
  }
  initComponent(){
    let _this=this;
    Vue.component('router-link',{  //在Vue中注册全局组件<router-link to='/about'>关于</router-link>
      props:{
        to:{
          type:String,
          default:""
        }
      },
      render(h){  //虚拟dom, h(tag,data,children),这里的this指的是router-link组件
        return h('a',{
          attrs:{
            href:"#"+this.to  //存在hash的情况是
          }
        },[this.$slots.default])   //this.$slots.default是匿名插槽相当于文本内容‘关于’
      }
    })

    Vue.component('router-view',{  //在Vue中注册全局组件<router-view />
      render(h){  //虚拟dom, h(tag,data,children)
        const comp=_this.routerMap[_this.app.current].component; 
        return h(comp)
      }
    })
  }
}



export default new ARouter({
  routes :[
    {
        path: '/',
        name: 'home',
        component: Home,
        beforeEnter(from,to,next){  //独享路由守卫

        },
      }
    ]
})

2.在main.js中调用ARouter.js:

import Vue from 'vue'
import App from './App.vue'
import ARouter from './ARouter.js'
Vue.use(ARouter); //即相当于调用ARouter的install方法,并把Vue作为参数传递进去。

new Vue({
  ARouter,
  render: h => h(App)
}).$mount('#app')
发布了200 篇原创文章 · 获赞 37 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/qq_42231156/article/details/103944101