Vue路由router详解

2022-04-15 0 348
目录
  • 模块化的方式使用路由插件
  • 使用路由
    • 声明式导航
    • 编程式导航
  • 动态路由匹配
    • 通配符匹配路径
      • 查询参数query
        • 响应路由参数的变化
          • 命名路由,路由别名,重定向
            • 嵌套路由
              • 命名视图
                • 导航守卫
                  • (1)全局守卫
                  • (2)路由独享守卫
                  • (3)组件内守卫
                  • 导航解析的流程
                • 总结

                  模块化的方式使用路由插件

                  (1)安装

                  npm install vue-router
                  

                  (2)构建文件目录

                  在src目录下创建一个router文件夹,然后创建一个index.js

                  Vue路由router详解

                  (3)这里我们通过模块化的方式进行创建路由,方便代码的管理,这里只是对路插件进行了注册,然后创建好路由对象。通过export default 关键字将创建好的路由对象暴露出去。

                  //index.js
                  import VueRouter from 'vue-router'
                  import Vue from 'vue'
                  import Home from "../views/Home";
                  Vue.use(VueRouter)//注册路由插件
                  export default  new VueRouter({
                      routes:[{
                          path:'/',
                          component:Home
                      }]
                  })
                  

                  (4)在入口文件main.js引入创建好的路由对象,并且把他挂载到Vue实例中。

                  //main.js
                  import Vue from 'vue'
                  import App from './App.vue'
                  import store from '@/store'
                  import router from '@/router'//这里就是引入了我们创建好的路由对象。模块化的编程思维
                  Vue.config.productionTip = false
                  Vue.prototype.bus = new Vue()
                  new Vue({
                    store,
                    router,
                    render: h => h(App),
                  }).$mount('#app')
                  

                  使用路由

                  声明式导航

                  可以理解成,通过标签进行跳转

                  声明式导航:<router-link :to="..."> 或者 <router-link to="...">

                  定义路由规则

                   {
                          path:'/',
                          component:Home
                          name:home
                      }
                  

                  (1)router-link导航标签to属性使用字符串方式

                   <router-link to="/">go to home</router-link>
                  

                  (2)router-link导航标签to使用对象的方式

                  使用路径进行匹配

                   <router-link :to="{path:'/'}">go to home</router-link>
                  

                  router-link导航标签to属性使用对象的方式并且使用路由名称进行匹配

                   <router-link :to="{name:'home'}">go to home</router-link>
                  

                  编程式导航

                  可以理解成JS进行跳转

                  编程式导航:router.push(...)

                  下面的例子包含了动态路由匹配和query查询参数的知识,不清楚的可以先看了这两者的内容再回来看此处的内容。

                  // 字符串
                  router.push('home')
                  // 对象
                  router.push({ path: 'home' })
                  // 命名的路由
                  router.push({ name: 'user', params: { userId: '123' }})
                  // 带查询参数,变成 /register?plan=private
                  router.push({ path: 'register', query: { plan: 'private' }})
                  

                  注意:如果提供了 path,params 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 与params配合或手写完整的带有参数的 path:

                  const userId = '123'
                  router.push({ name: 'user', params: { userId }}) // -> /user/123
                  router.push({ path: `/user/${userId}` }) // -> /user/123
                  // 这里的 params 不生效
                  router.push({ path: '/user', params: { userId }}) // -> /user
                  

                  动态路由匹配

                  定义路由规则

                   {
                          path:'/user/:id',
                          component:User
                          name:user
                      }
                  
                   <router-link to="/user/01">go to home</router-link>
                  
                   <router-link :to="{path:'/user/01'}">go to home</router-link>
                  
                   <router-link :to="{name:'/user',params={id:'01'}}">go to home</router-link>
                  

                  通过如上的方式进行定义,可以通过$route.params.id 获动态路由参数:id值为’01‘

                  注意:

                  当使用对象的方式进行匹配时候,不能通过path和params的方式。只能通过name和params的方式

                  如下方式,不能匹配到路由规则{path:’/user/:id’} ,如下表述只能被理解成’/user’,

                  即使通过*通配符匹配到该路由,params也不会被传递过去,因为要有path这个属性就不会去解析params的属性了。

                  {
                    // 会匹配所有路径
                    path: '*'
                  }
                  {
                    // 会匹配以 `/user-` 开头的任意路径
                    path: '/user-*'
                  }
                  

                  通配符匹配路径

                  我们通常使用*捕获其他意外的路径,进行个兜底的处理,通常将其导航到404错误页面。

                  <router-link to=“/user?name=zhangsan">...</router-link>
                  <router-link :to="{path:'/user?zhangsan'}">...</router-link>
                  <router-link :to="{path:'/user',query:{name:'zhangsan'}}">...</router-link>
                  <router-link :to="{name:'user',query:{name:'zhangsan'}}">...</router-link>
                  

                  当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分

                  查询参数query

                  <router-link to=“/user?name=zhangsan">...</router-link>
                  <router-link :to="{path:'/user?zhangsan'}">...</router-link>
                  <router-link :to="{path:'/user',query:{name:'zhangsan'}}">...</router-link>
                  <router-link :to="{name:'user',query:{name:'zhangsan'}}">...</router-link>
                  

                  查询参数不想动态路由参数匹配那样,就算使用了path,依然可以使用query进行传参;

                  以上query传递过来的参数可以通过this.$route.query.name进行获取。

                  响应路由参数的变化

                  如果路由从/user/01导航到/user/02,原来的组件实例会被复用。因为有两个路由都渲染同一个组件,这意味着组件的生命周期钩子不会被再次调用。因此需要通过其他方式进行监听参数的变化来做出响应。

                  (1)通过watch进行监听

                  const User = {
                    template: '...',
                    watch: {
                      $route(to, from) {
                        // 对路由变化作出响应...
                      }
                    }
                  }
                  

                  (2)通过导航守卫进行监听

                  const User = {
                    template: '...',
                    beforeRouteUpdate(to, from, next) {
                      // react to route changes...
                      // don't forget to call next()
                    }
                  }
                  

                  命名路由,路由别名,重定向

                  特别地我把这三者的概念放在一起来阐述,是为了更好的去区分他们之间的区别。这些内容都是在路由规则去配置的

                  {
                          path: '/pageOne',
                          component:PageOne,
                          alias:"/firstPage",
                          name:"pageOne",
                          redirect:{name:'pageTwo'}
                      },
                      {
                          path: '/pageTwo',
                          component:PageTwo,
                          name:'pageTwo'
                      }
                  

                  (1)命名路由:可以理解成给这个路由取个名字

                  即使通过name属性给路由取一个名字

                  routes: [
                      {
                        path: '/user/:userId',
                        name: 'user',
                        component: User
                      }
                    ]
                  

                  (2)路由别名:可以理解成这个路由的第二个名字。

                  例如:/a的别名是/b,当用户访问/b的时候,URL会保持/b但是路由匹配到的内容则为/a,也就是知识URL内容显示/b内容实则是/a

                  注意了:这里别名要使用路径的方式去表述,而不是跟命名路由那样直接写名字哦~

                  const router = new VueRouter({
                    routes: [
                      { path: '/a', component: A, alias: '/b' }
                    ]
                  })
                  

                  (3)重定向:可以理解为访问/a的时候直接跳转到/b

                  重定向的表述有三种形式:

                  • 字符串
                  const router = new VueRouter({
                    routes: [
                      { path: '/a', redirect: '/b' }
                    ]
                  })
                  
                  • 对象
                  const router = new VueRouter({
                    routes: [
                      { path: '/a', redirect: { name: 'foo' }}
                    ]
                  })
                  
                  • 方法
                  const router = new VueRouter({
                    routes: [
                      { path: '/a', redirect: to => {
                        // 方法接收 目标路由 作为参数
                        // return 重定向的 字符串路径/路径对象
                      }}
                    ]
                  })
                  

                  嵌套路由

                  嵌套路由可以这么理解,所匹配的路由渲染出来的组件中包含路由组件,’/user’当我们匹配到一个路由渲染出一个组件User,但是如果想继续在User组件的<router-view ></router-view>继续匹配。则我们要通过/user/childRouteName进一步匹配。”childRouteName”就是我们路由规则children中对应的path的值啦。

                   {
                        path: '/user',
                        component: User,
                        children: [
                          {
                            // 当 /user//profile 匹配成功,
                            // UserProfile 会被渲染在 User 的 <router-view> 中
                            path: 'profile',
                            component: UserProfile
                          },
                          {
                            // 当 /user//posts 匹配成功
                            // UserPosts 会被渲染在 User 的 <router-view> 中
                            path: 'posts',
                            component: UserPosts
                          }
                        ]
                      }
                  

                  APP.Vue中

                  <div id="app">
                    <router-view></router-view>
                  </div>
                  

                  User组件中

                  const User = {
                    template: `
                      <div class="user">
                        <span>User组件</span>
                        <router-view></router-view>
                      </div>
                    `
                  }
                  

                  注意:

                  定义了嵌套路由,即定义了children的情况下,必须是完整的路由才可以匹配正确。也就是 当 /user/profile匹配成功,但是/user这样是无法匹配成功的。

                  命名视图

                  当一个组件上同时渲染多个视图,注意是同级展示多个视图,而不是嵌套展示。那此时就可以通过命名视图来解决这个问题。
                  路由规则定义

                  {
                          path:"/namingRoute",
                          components:{//注意此处components是带's'结尾的,之前单个的时候是不带的。
                              default:Home,
                              one:PageOne,
                              two:PageTwo
                          }
                      }
                  

                  组件定义

                   	<router-view></router-view>//渲染default对应的组件
                      <router-view name="one"></router-view>//渲染one对应的组件
                      <router-view name="two"></router-view>//渲染two对应的组件
                  

                  当URL为:/namingRoute的时候 匹配到该路由,则会按照对应的router-view视图组件进行渲染。

                  导航守卫

                  (1)全局守卫

                  可以理解成通过全局router实例对象router进行定义的守卫。

                  • route.beforeEach(全局前置守卫)

                  使用方式:

                  beforeEach((to,from,next)=>{
                  	//...
                  })
                  
                  • router.beforeResolve(全局解析守卫)

                  在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用

                  使用方式:

                  router.beforeResolve((to, from, next) => {
                    // ...
                  })
                  
                  • router.afterEach (全局后置钩子)

                  钩子不会接受 next 函数也不会改变导航本身:

                  使用方式:

                  router.afterEach((to, from) => {
                    // ...
                  })
                  
                  使用的位置:通常在router文件夹下的index.js
                  const router = new VueRouter({ ... })
                  //全局前置守卫
                  router.beforeEach((to, from, next) => {
                    // ...
                  })
                  //全局解析守卫
                  router.beforeResolve((to, from, next) => {
                    // ...
                  })
                  //全局后置钩子
                  router.afterEach((to, from) => {
                    // ...
                  })
                  

                  (2)路由独享守卫

                  可以理解成在路由规则上定义的守卫

                  • beforeEnter

                  (3)组件内守卫

                  可以理解成在组件内定义的守卫

                  • beforeRouteEnter

                  还没有创建组件实例,在该路由被confirm前调用。

                  const User = {
                    template: `...`,
                    beforeRouteEnter(to, from, next) {
                      // 在渲染该组件的对应路由被 confirm 前调用
                      // 不!能!获取组件实例 `this`
                      // 因为当守卫执行前,组件实例还没被创建
                    }
                  }
                  

                  注意:

                  该守卫不能直接使用this访问vue实例对象,因为此时组件实例还没有被创建。但是可以通过给next方法传递回调来方位组件的实例。

                  给next()传递回调,仅在beforeRouteEnter使用有效!!!

                  beforeRouteEnter (to, from, next) {
                    next(vm => {
                      // 通过 `vm` 访问组件实例
                    })
                  }
                  
                  • beforeRouteUpdate (2.2 新增)

                  在路由改变且该组件被服用时调用

                  const User = {
                    template: `...`,
                    beforeRouteUpdate(to, from, next) {
                      // 在当前路由改变,但是该组件被复用时调用
                      // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
                      // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
                      // 可以访问组件实例 `this`
                    }
                  }
                  
                  • beforeRouteLeave

                  在导航离开该组件对应的路由时调用

                  const User = {
                    template: `...`,
                    beforeRouteLeave(to, from, next) {
                      // 导航离开该组件的对应路由时调用
                      // 可以访问组件实例 `this`
                    }
                  }
                  

                  导航解析的流程

                  正常首次访问路由的执行顺序

                  • beforeEach 全局的路由前置守卫
                  • beforeEnter 独享路由守卫
                  • beforeRouteEnter 组件路由守卫
                  • beforeResolve 全局路由解析守卫
                  • afterEach 全局路由后置钩子
                  • Dom渲染
                  • 调用beforeRouteEnter 组件路由守卫中传递给next的回调函数。并且把创建号的组件实例作为回调函数的参数传入。

                  总结

                  本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注NICE源码的更多内容!

                  免责声明:
                  1、本网站所有发布的源码、软件和资料均为收集各大资源网站整理而来;仅限用于学习和研究目的,您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 不得使用于非法商业用途,不得违反国家法律。否则后果自负!

                  2、本站信息来自网络,版权争议与本站无关。一切关于该资源商业行为与www.niceym.com无关。
                  如果您喜欢该程序,请支持正版源码、软件,购买注册,得到更好的正版服务。
                  如有侵犯你版权的,请邮件与我们联系处理(邮箱:skknet@qq.com),本站将立即改正。

                  NICE源码网 JavaScript Vue路由router详解 https://www.niceym.com/26236.html