vue路由机制

目录

路由机制

动态路由匹配

嵌套路由

编程式导航

路由组件传参

path-query传参

name-params传参

路由模式

hash模式

history模式

vue-router使用的模式

导航守卫 --路由的改变会触发导航守卫

全局守卫

全局前置守卫

全局后置钩子

路由独享守卫

组件内的守卫           


路由机制

vue-router是vue的一个插件,用来提供路由功能。通过路由的改变可以动态加载组件,达到开发单页面程序的目的。

安装

方式一 : CDN引入

<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.6.5/vue-router.js"></script>

方式二:本地引入

<script src='vue.js'></script>
<script src='vue-router.js'></script>

方式三 : cnpm下载

 cnpm install vue-router

使用

在html文件中使用时需要引入vueRouter(先引入vue.js,在引入vueRouter)

<script>
  // 声明组件
  let myA = {
    template: `
        <div>A组件</div>
      `
  };
  let myB = {
    template: `
        <div>B组件</div>
      `
  };
  // 1.定义路由对象数组 route路由对象  router路由器对象  routes路由对象组
  let routes = [{
    path: '/a',
    component: myA
  }, {
    path: '/b',
    component: myB
  }];
  // 2.创建路由器对象  声明路由器实例对象
  let router = new VueRouter({
    // 声明配置路由对象
    routes: routes
  })
  // 3.注册路由器对象
  new Vue({
    el: '#app',
    // 将路由实例对象导入vue实例,相当于router:router,在此使用简写形式
    router,
    components: {
      'my-a': myA,
      'my-b': myB
    },
    data: {
      msg: 'hello'
    },

  })
</script>

<div id="app">
    {{msg}}
     <!-- 4.实现路由切换,router-link的本质是创建a标签 -->
     <div>
         <router-link to="/a">去A路由</router-link>
         <router-link to="/b">去B路由</router-link>
         <a href="#/a">a标签路由去A</a>
       </div>
     <div>
         <!-- 路由组件显示的位置  路由出口,将匹配到的路由组件,渲染到此-->
         <router-view></router-view>
       </div>
   </div>
let routes=[
  {
       path:"/",
       //路由名称
       name:"aRoute",
       //别名 重命名
       alias:'/aa',
       //重定向
       // redirect:'/a'
       redirect:{name:'aRoute'}
  }
]

动态路由匹配

需要把某种模式匹配到的所有路由,全部映射到同一个组件。

例如 : 有一个user组件,对于所有id不同的用户,都要使用这个组件来渲染,那么可以在vue-router的路由路径中使用动态路径参数来达到这个效果。

复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch $route 对象,或者使用组件内部的导航守卫

<div id="app">
    {{msg}}
     <!-- 4.使用路由 -->
     <div>
         <router-link to="/user/id/1/username/zhangsan">去A路由</router-link>
       </div>
     <div>
         <!-- 路由组件显示的位置 -->
         <router-view></router-view>
       </div>
   </div>
// 声明组件
<script>
  let myA = {
    data() {
      return {
        id: null,
        username: ''
      }
    },
    template: `
         <div>A组件{{id}}--{{username}}</div>
       `,
    /* created() {
      alert(1);
      // console.log(this.$route);
      this.id = this.$route.params.id;
      this.username = this.$route.params.username;
    } */
    //监听
    /* watch: {
      msg(newValue, oldValue) { },
      $route:{
          handler(){
            // to是新路由  from是旧路由
        // console.log(to, from);
        this.id = this.$route.params.id;
        this.username = this.$route.params.username;
          },
          deep:true
      }
    } */
    // 监听路由发生变化 路由守卫
    beforeRouteUpdate(to, from, next) {
      // console.log(to.params);
      this.id = to.params.id;
      this.username = to.params.username;
      // 继续
      // next();
      // 阻断
      // next(false)
    }
  };
  let myB = {
    template: `
         <div>B组件</div>
       `
  };
  // 1.定义路由对象数组 route路由对象  router路由器对象  routes路由对象组
  let routes = [{
    // 动态路由
    //  /user/id/1/username/zhangsan  
    //  /user/id/2/username/lisi  
    path: '/user/id/:id/username/:username',
    component: myA
  }];
  // 2.创建路由器对象
  let router = new VueRouter({
    routes: routes
  })
  // 3.注册路由器对象
  new Vue({
    el: '#app',
    router: router,
    components: {
      'my-a': myA,
      'my-b': myB
    },
    data: {
      msg: 'hello'
    },
    methods: {}
  })
</script>

嵌套路由

实际生活中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件 :

<body>
  <div id="app">
    <router-link to='user'>去用户</router-link>
    <router-link to='manager'>去管理员</router-link>
    <router-view></router-view>
  </div>
</body>
<script>
  // 创建一个组件
  let user = {
    template: `
                 <div>
                     <router-link to='/userChild1'>子组件1</router-link>
                     <router-link to='/userChild2'>子组件2</router-link>
                     <router-view ></router-view>
                 </div>
             `
  }
  let manager = {
    template: `
                 <div>管理员</div>
             `
  }
  let userChild1 = {
    template: `
                 <div>子组件1</div>
             `
  }
  let userChild2 = {
    template: `
                 <div>子组件2</div>
             `
  }
  let routes = [{
    path: '/manager',
    component: manager
  }, {
    path: '/user',
    component: user,
    redirect: '/userChild1',
    children: [{
      path: "/userChild1",
      component: userChild1
    }, {
      path: "/userChild2",
      component: userChild2
    }]
  }];
  let router = new VueRouter({
    routes
  })
  new Vue({
    el: "#app",
    router,
    data: {

    }
  })

编程式导航

除了使用 <router-link> 创建 a 标签来定义导航链接,还可以借助 router 的实例方法,通过编写代码来实现。this.$router.push()跳转到指定路由,会向history栈添加一个新的记录,当用户点击浏览器回退按钮的时候,可以回到跳转前的url。

<script>
  // 创建A B组件
  let myA = {
    data() {
      return {

      }
    },
    template: `
             <div>
                 A组件
             </div>
         `,
    created() {
      console.log(this.$route)
    },

  }
  let myB = {
    data() {
      return {

      }
    },
    template: `
             <div>
                 B组件
             </div>
         `
  };
  // 创建路由组件对象数组 routes router路由器对象 route路由对象
  let routes = [
    {
      path: "/a",
      component: myA,
      name: 'mya'
    },
    {
      path: "/b",
      component: myB,


    }
  ];
  // 创建路由器对象实例
  let router = new VueRouter({
    // 配置路由对象组
    routes
  })

  new Vue({
    el: '#app',
    data: {

    },

    // 3.注册路由
    router,
    components: {
      'my-a': myA,
      'my-b': myB
    },
    methods: {
      toPath() {
        this.$router.push({

          path: "/a",
          // 有效
          // query:{id:1},
        })
      },
      toPath1() {
        this.$router.push({
          name: 'mya',
          query: { id: 1 },
          // 参数是一次性携带刷新页面 params失效
          params: {
            name: "terry"
          }
        }),
        //  this.$router.replace({
		//	path:"/column",
		//	query:{id:1}
		//  })
      }
    }
  })
</script>
<div id="app">
    <router-link to='/a'>去a路由</router-link>
    <router-link to='/b'>去b路由</router-link>
    <a href="#/a/2">去a路由</a>
    <button @click="$router.push('/a')">跳转到A路由</button>
    <button @click="$router.push('a')">跳转到A2路由</button>
    <button @click="toPath">跳转到A3路由</button>
    <button @click="toPath1">跳转到A4路由</button>
    <router-view></router-view>
</div>
//跳转到指定页面 可传递参数
前进一步记录
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,则会报错
router.go(-100)
router.go(100)

路由组件传参

路由传递是指,从A页面跳转到B页面时,将A页面中的变量传递给B页面使用,传递参数的方式有两种 :

path-query传参

使用path与query结合的方式传递参数时,参数会被拼接在浏览器地址栏中,并且刷新页面后数据也不会丢失。

name-params传参

path-query传参

<script>
  let user = {
    template: `
      <div @click="userHandler">普通用户,点击此处可跳转至管理员页面</div>
    `,
    data() {
      return {
        list: "hello",
        obj: {
          name: 'tom',
          age: 3
        }
      }
    },
    methods: {
      userHandler() {
        // 跳转
        this.$router.push({
          path: '/manager',
          query: {
            list: this.list,
            obj: JSON.stringify(this.obj)
          }
        })
      }
    },
  }
  let manager = {
    template: `
      <div>管理员 {{$route.query.list}}  {{$route.query.obj}}</div>
    `
  }
  let router = new VueRouter({
    routes: [{
      path: '/user',
      component: user
    }, {
      path: '/manager',
      component: manager
    }]
  })
  new Vue({
    el: "#app",
    router
  })
</script>
<div id="app">
	<router-link to="/user">user</router-link>
	<router-link to="/manager">manager</router-link>
	<router-view></router-view>
</div>

name-params传参

<script>
  let user = {
    template: `
      <div @click="userHandler">普通用户,点击此处可跳转至管理员页面</div>
    `,
    data() {
      return {
        list: "hello",
        obj: {
          name: 'tom',
          age: 3
        }
      }
    },
    methods: {
      userHandler() {
        // 跳转
        this.$router.push({
          name: 'manager',
          params: {
            list: this.list,
            obj: JSON.stringify(this.obj)
          }
        })
      }
    },
  }
  let manager = {
    template: `
      <div>管理员 {{$route.params.list}}  {{$route.params.obj}}</div>
    `
  }
  let router = new VueRouter({
    routes: [{
      path: '/user',
      component: user,
      name: 'user'
    }, {
      path: '/manager',
      component: manager,
      name: 'manager'
    }]
  })
  new Vue({
    el: "#app",
    router
  })
</script>

<div id="app">
	<router-link to="/user">user</router-link>
	<router-link to="/manager">manager</router-link>
	<router-view></router-view>
</div>

路由模式

hash模式

hash模式的工作原理是hashchange事件,可以在window监听hash的变化。我们在url后面随便添加一个#xx触发这个事件。

window.onhashchange = function(event){ console.log(event); // 打印出一个HashChangeEvent事件对象,在该对象内有newURL和oldURL // location.hash中也有相关的信息 // 假设hash值是个颜色值,通过location.hash来获取到对应的hash值,然后设置页面中的某个元素的背景颜色来改变页面 }

history模式

把window.history对象打印出来可以看到里边提供的方法和记录长度 history对象内有back(),forword(),go()等方法 前进,后退,跳转操作方法:

history.go(-3);//后退3次 history.go(2);//前进2次 history.go(0);//刷新当前页面 history.back(); //后退 history.forward(); //前进

vue-router使用的模式

vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。如果不想要很丑的 hash,可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。不过这种模式要玩好,还需要后台配置支持。

hash路由和history路由的区别:

1.hash路由在地址栏URL上有#,而history路由没有会好看一点

2.进行回车刷新操作,hash路由会加载到地址栏对应的页面,而history路由一般就404报错了(刷新是网络请求,没有后端准备时会报错)。

3.hash路由支持低版本的浏览器,而history路由是HTML5新增的API。

4.hash的特点在于它虽然出现在了URL中,但是不包括在http请求中,所以对于后端是没有一点影响的,所以改变hash不会重新加载页面,所以这也是单页面应用的必备。

5.history运用了浏览器的历史记录栈,之前有back,forward,go方法,之后在HTML5中新增了pushState()和replaceState()方法(需要特定浏览器的支持),它们提供了对历史记录进行修改的功能,不过在进行修改时,虽然改变了当前的URL,但是浏览器不会马上向后端发送请求。

导航守卫 --路由的改变会触发导航守卫

全局守卫

全局守卫有全局前置守卫、全局后置守卫。

const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... })

const router = new VueRouter({ ... }) router.afterEach((to, from) => { // ... })

路由独享守卫

组件内守卫

beforeRouteEnter: (to, from, next) => { //不!能!获取组件实例 this } beforeRouteUpdate (to, from, next) {//在当前路由改变,但是该组件被复用时调用,可访问this} beforeRouteLeave (to, from, next) {//导航离开该组件的对应路由时调用,可访问this}

全局前置守卫
let router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
	// ...
})
全局后置钩子
let router = new VueRouter({ ... })
router.afterEach((to, from) => {
	// ...
})

全局守卫参数说明:
​​​​​​* to: Route : 即将要进入的目标路有对象
* from: Route : 当前导航正要离开的路由
* next: Function : 一定要调用该方法来**resolve**这个钩子。执行效果依赖 next 方法的调用参数

路由独享守卫

可以在路由配置上直接定义 beforeEnter 守卫,改守卫与全局前置守卫的方法参数是一样的 :
​​​​

let router = new VueRouter({
  routes: [
    {
      path: '/home',
      component: Home,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

组件内的守卫
          

beforeRouteEnter(to,from,next){
    // this--window
    console.log(this,'beforeRouteEnter');
    next()
    },
beforeRouteUpdate(to,from,next){
    //this--组件实例
    console.log(this,'beforeRouteUpdate');
    next()
},
beforeRouteLeave(to,from,next){
    //this--组件实例
    console.log(this,'beforERouteLeave')
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学前端的狗头苏丹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值