zoukankan      html  css  js  c++  java
  • vue-learning:39

    vue-router路由的基本使用

    一张图阐述vue-router的基本使用步骤
    router

    // 0. 如果全局使用CDN引入:vue 引入在前,vue-router引入在后
    // <script src="https://unpkg.com/vue/dist/vue.js"></script>
    // <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    // 如果模块化工程,已安装:npm install vue-router
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    Vue.use(VueRouter)
    
    // 1. 定义 (路由) 组件。
    // 可以从其他文件 import 进来
    // const Foo = () => import(./foo)
    const Foo = { template: '<div>foo</div>' }
    const Bar = { template: '<div>bar</div>' }
    
    // 2. 定义路由
    // 每个路由应该映射一个组件。 其中"component" 可以是
    // 通过 Vue.extend() 创建的组件构造器,
    // 或者,只是一个组件配置对象。
    // 我们晚点再讨论嵌套路由。 
    const routes = [
      { path: '/foo', name: 'foo', component: Foo },
      { path: '/bar', name: 'bar', component: Bar }
    ]
    
    // 3. 创建 router 实例,然后传 `routes` 配置
    // 你还可以传别的配置参数, 不过先这么简单着吧。
    const router = new VueRouter({
        // 还有其它配置项
      routes // (缩写) 相当于 routes: routes
    })
    
    // 4. 创建和挂载根实例。
    // 记得要通过 router 配置参数注入路由,
    // 从而让整个应用都有路由功能,在任意组件实例中都可以调用this.$router  this.$route
    const app = new Vue({
      router
    }).$mount('#app')
    
    <div id="app">
      <h1>Hello App!</h1>
      <p>
        <!-- 使用 router-link 组件来导航.也可以在js中使用编程式导航 -->
        <!-- 通过传入 `to` 属性指定链接. -->
        <!-- <router-link> 默认会被渲染成一个 `<a>` 标签,也可以通过tag属性定义 -->
        <router-link to="/foo">Go to Foo</router-link>
        <router-link to="/bar">Go to Bar</router-link>
      </p>
      <!-- 路由出口 -->
      <!-- 路由匹配到的组件将渲染在这里 -->
      <router-view></router-view>
    </div>
    

    option配置项

    const router = new VueRouter(option)
    
    const option = {
        routes: routeConfig,   // 路由对象,单独讲解,见下面
        // 路由模式,在浏览器端只有两种:hash / history,默认hash。nodejs环境下默认abstract
        mode: "hash" | "history" | "abstract",
        base: "/", // 应用的基路径。
        linkActiveClass: "router-link-active",  // 全局配置激活导航的类名,默认值router-link-active
        linkExactActiveClass: "router-link-exact-active", // 全局配置精确激活的导航类名,即只应用于当前导航项
        //定义滚动行为,返回一个位置坐标
        scrollBehavior: (to,from,savedPosition) => {/** do something */ return  PositionDescriptor[,Promise<PositionDescriptor>]},
        // 当浏览器不支持 history.pushState 控制路由是否应该回退到 hash 模式。默认值为 true。
        fallback: true, 
        // 提供自定义查询字符串的解析/反解析的函数。覆盖默认行为。
        parseQuery,
        stringifyQuery,
    }
    

    route

    1. route定义
      const routeConfig = [
          {
              name?: string, // 命名路由
              path: string, // 声明路由路径
              component: '', // 该路由关联的组件,可以实现懒加载,接受异步返回组件的Promise对象。
              components?: { [name: string]: Component }, // 命名视图组件
              children?: Array<RouteConfig> // 定义嵌套路由
              redirect?: string | Location | Function, // 指定重定向路由,接受字符串、对象、函数返回的路径或对象
              alias?: string | Array<string>, // 路由别名
              meta: {}, // 自定义路由的元信息,可以通过$route.meta获取
              props?: boolean | Object | Function, // boolean/object/function,允许指定为组件传递prop的方式。
              beforeEnter: (to,from,next) => {/** do something*/  next()}, // 路由独享守卫
          }
      ]
    
    1. route路由对象
      一个页面路径就含有一个route路由对象,可以用this.$route获取。
      this.$route = {
          name: '', // 当前路由的名称,建议定义时加上。
          path: '', // 字符串形式,对应当前路由的绝对路径,如 "/foo/bar"
          fullPath: '', // 完整的URL,包含查询参数和 hash 的完整路径。
          hash: '', // 当前路由的 hash 值 (带 #) ,如果没有 hash 值,则为空字符串。
          matched: [], // 一个数组,包含当前路由的所有嵌套路径片段的路由记录,比如包含children的嵌套路由
          params: {}, // 路由参数对象,一个 key/value 对象,对应路径/foo/:id,则$route.params.id如果没有则为一个空对象
          query: {}, // 一个 key/value 对象,表示 URL 查询参数。例如,对于路径 /foo?user=1,则有 $route.query.user == 1,如果没有查询参数,则是个空对象。
          meta: {}, // 路由元信息
          redirectedFrom: '', // 如果存在重定向,即为重定向来源的路由的名字
      }
    

    router路由器实例对象

    1. router对象属性
      this.$router.app  //router所在的vue根实例
      this.$router.mode // 路由使用的模式:hash 或 history
      this.$router.currentRoute // 当前页面的路由对象,同this.$route
    
    1. router对象的方法
      // 编程式导航方法
      // router.push('home')  字符串
      // router.push({ path: 'home' }) 对象
      // router.push({ name: 'user', params: { userId: '123' }}) // 命名路由,params必须与name同时存在才有效,单独与path存在无效。
      // router.push({ path: 'register', query: { plan: 'private' }}) // 带查询参数,变成 /register?plan=private
      router.push(location, onComplete?, onAbort?)
      router.replace(location, onComplete?, onAbort?) // 同push
      router.go(n)
      router.back()
      router.forward()
    
      // 全局导航守卫,见路由钩子函数
      router.beforeEach((to, from, next) => {/* must call `next` */next()})
      router.beforeResolve((to, from, next) => {/* must call `next` */,next()})
      router.afterEach((to, from) => {})
    
      // 动态添加更多的路由规则。参数必须是一个符合 routes 选项要求的数组。
      router.addRoutes(routes: Array<RouteConfig>)
    
      // 路由加载的完工事件
      router.onReady(callback, [errorCallback])
      router.onError(callback)
      // 错误捕获:
      // 在一个路由守卫函数中被同步抛出;
      // 在一个路由守卫函数中通过调用 next(err) 的方式异步捕获并处理;
      // 渲染一个路由的过程中,需要尝试解析一个异步组件时发生错误。
    

    路由钩子函数

      // 全局守卫,在router对象中声明
      router.beforeEach((to, from, next) => {/* must call `next` */next()})
      router.beforeResolve((to, from, next) => {/* must call `next` */,next()})
      router.afterEach((to, from) => {})
    
      // 路由独享守卫,在route中声明
      beforeEnter: (to,from,next) => {/** do something*/  next()}, // 路由独享守卫
    
      // 组件守卫,在组件实例选项对象option中声明
      beforeRouteEnter (to, from, next) {
      // 在渲染该组件的对应路由被 confirm 前调用
      // 不!能!获取组件实例 `this`,因为当守卫执行前,组件实例还没被创建
      // 但是可以传入一个回调,next(vm => {// 通过 `vm` 访问组件实例})
      },
      beforeRouteUpdate (to, from, next) {
      // 在当前路由改变,但是该组件被复用时调用
      // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
      // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
      // 可以访问组件实例 `this`
      },
      beforeRouteLeave (to, from, next) {
      // 导航离开该组件的对应路由时调用
      // 可以访问组件实例 `this`
      }
    

    钩子函数的参数

    • to: Route对象- 即将要进入的目标路由

    • from: Route对象- 当前导航正要离开的路由

    • next: Function: 一定要调用该方法来执行resolve 这个钩子,否则不会被resolved,程序被无限等待。next方法的调用参数:

      • next(): 直接进行管道中的下一个钩子。
      • next(false): 中断当前的导航。
      • next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
      • next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。

    导航守卫被解析完整流程

      1.导航被触发。
      2.在失活的组件里调用离开守卫beforeRouteLeave。
      3.调用全局的 beforeEach 守卫。
      4.在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
      5.在路由配置里调用 beforeEnter。
      6.解析异步路由组件。
      7.在被激活的组件里调用 beforeRouteEnter。
      8.调用全局的 beforeResolve 守卫 (2.5+)。
      9.导航被确认。
      10.调用全局的 afterEach 钩子。
      11.触发 DOM 更新。
      12.用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。
    

    router-hooks

    • to
      <!-- 与$router.push写法基本一样 -->
      <!-- 字符串 -->
      <router-link to="home">Home</router-link>
      <!-- 使用 v-bind 的 JS 表达式 -->
      <router-link v-bind:to="'home'">Home</router-link>
    
      <!-- 不写 v-bind 也可以,就像绑定别的属性一样 -->
      <router-link :to="'home'">Home</router-link>
    
      <!-- 同上 -->
      <router-link :to="{ path: 'home' }">Home</router-link>
    
      <!-- 命名的路由 -->
      <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
    
      <!-- 带查询参数,下面的结果为 /register?plan=private -->
      <router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>
    
    • replace
     <!-- 设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录。 -->
     <router-link :to="{ path: '/abc'}" replace></router-link>
    
    • tag
      <!-- 默认为a标签 -->
      <router-link to="home">Home</router-link>
      <!-- 渲染结果 -->
      <a href="home">Home</a>
    
      <!-- 有时候想要 <router-link> 渲染成某种标签,例如 <li>。 于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航。 -->
      <router-link to="/foo" tag="li">foo</router-link>
      <!-- 渲染结果 -->
      <li>foo</li>
    
    • active-class
    • exact-active-class
    • exact
      active-class
      自定义链接激活时使用的 CSS 类名 ,也可以通过路由的构造选项 linkActiveClass 来全局配置。
      exact-active-class
      配置当链接被精确匹配的时候应该激活的 class。注意默认值也是可以通过路由构造函数选项 linkExactActiveClass 进行全局配置的。
      exact
      是否执行精确匹配路径,来使用设置的激类
    
    • append
      是否在当前 (相对) 路径前添加基路径,即base的值
    
    • event
      声明可以用来触发导航的事件,默认click
    

    • name
      如果 <router-view name="">设置了名称,则会渲染对应的命名路由配置中 components 下的相应组件。

    路由传递参数的方式

    • 方式一:路由动态参数
      // route配置
      {
          path: '/user/:userId',
          name: '***',
          component: ***
      }
    
      // 路由跳转
      this.$router.push({path:`/user/${userId}`})
    
      // 目标组件内接收参数
      this.$route.params.userId
    
    • 方式二:命名路由传参,使用name和params
      // 前提对应route有配置name
      // 跳转跳转
      this.$router.push({name:'Login',params:{id:'leelei'}})
    
      // 目标组件内接收参数
      this.$route.params.id
    
    • 方式三:查询参数传参,使用path和query
      // 此时url会携带query: /login?id=leelei
      this.$router.push({path:'/login',query:{id:'leelei'})
    
      // 目标组件内接收参数
      this.$route.query.id
    

    query传参是针对path的,params传参是针对name的。

    • 方式四:prop
      // 目标组件
      const User = {
        props: ['id'],
        template: '<div>User {{ id }}</div>'
      }
    
    • props:Boolean
      当route配置中props:true时,不管是动态参数路由/user/:id,还是通过命名路由(name和params)传递的参数,params的值都会传入组件内的props。
      // 对应的route配置props
      const router = new VueRouter({
        routes: [
          { path: '/user/:id', component: User, props: true },
        ]
      })
    
      // 跳转目标组件,此时user组件接收的props中的id=314391
      this.$router.push('/user/314391')
    
    • props: Object
      如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。
      const router = new VueRouter({
        routes: [
          { path: '/user', component: User, props: { id: 314391 } }
        ]
      })
    
    • props: Function
      如果props是一个函数形式,函数默认参数route对象,这样你便可以复用route对象属性,动态传值。props也将变成动态形式,类似父子组件动态值参。比如将静态值与基于路由的值结合等等。
      const router = new VueRouter({
        routes: [
          { path: '/user', component: User, props: (route) => ({ query: route.query.q }) }
        ]
      })
    

    此时/search?q=314391 会将 {query: '314391'} 作为属性传递给 User 组件。

    通过路由传入props不被this.$attrs接收

    看一个官方例子

      <!-- 用记事本新建一个html,复制代码保持,直接在浏览器打开查看效果 -->
      <!DOCTYPE html>
      <html lang="zh">
      <head>
          <meta charset="UTF-8">
          <title>Document</title>
      </head>
      <body>
          <div id="app">
              <h1>Route props</h1>
              <ul>
                  <li><router-link to="/">/</router-link></li>
                  <li><router-link to="/hello/you">/hello/you</router-link></li>
                  <li><router-link to="/static">/static</router-link></li>
                  <li><router-link to="/dynamic/1">/dynamic/1</router-link></li>
                  <li><router-link to="/attrs">/attrs</router-link></li>
              </ul>
              <button @click="handleClick">编程式导航传递参</button>
              <router-view class="view" foo="123"></router-view>
          </div>
      </body>
      <script src="https://unpkg.com/vue"></script>
      <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
      <script>
      const Hello = Vue.extend({
          template: `<div>
                      <h2 class="hello">Hello {{name}} {{ $attrs }}</h2>
                  </div>`,
          props: {
              name: {
                  type: String,
                  default: 'Vue!'
              }
          }
      })
    
      function dynamicPropsFn (route) {
        const now = new Date()
        return {
          name: (now.getFullYear() + parseInt(route.params.years)) + '!'
        }
      }
    
      const router = new VueRouter({
      //   mode: 'history',
      //   base: __dirname,
        routes: [
          { path: '/', component: Hello }, // No props, no nothing
          { path: '/hello/:name', component: Hello, props: true }, // Pass route.params to props
          { name: 'push', path: '/push', component: Hello, props: true }, // Pass route.params to props
          { path: '/static', component: Hello, props: { name: 'world' }}, // static values
          { path: '/dynamic/:years', component: Hello, props: dynamicPropsFn }, // custom logic for mapping between route and props
          { path: '/attrs', component: Hello, props: { name: 'attrs' }}
        ]
      })
    
      const vm = new Vue({
          el: "#app",
          router,
          methods: {
              handleClick() {
                  this.$router.push({
                      name: 'push',
                      params: {
                          name: 'push'
                      }
                  })
              }
          }
      })
      </script>
      </html>
    
    • 方式五:路由元信息meta携带数据
      // 定义路由时,定义元信息
      const routes = [
        { path: '/foo', name: 'foo', component: Foo, meta: {someData:'someData'} },
        { path: '/bar', name: 'bar', component: Bar }
      ]
      // 获取数据
      this.$route.meta.someData
    
  • 相关阅读:
    《TomCat与Java Web开发技术详解》(第二版) 第六章节的学习总结 ---- JSP技术
    《Lucene in Action 第二版》第三章节的学习总结----IndexSearcher以及Term和QueryParser
    《TomCat与Java Web开发技术详解》(第二版) 第六章节对应CD附带的helloapp无法启动的问题解决
    《TomCat与Java Web开发技术详解》(第二版) 第五章节的学习总结 ---- Servlet的高级用法
    《Lucene in Action》(第二版) 第二章节的学习总结 ---- IndexWriter+Document+Field
    《Lucene in Action》(第二版) 第一章节的学习总结 ---- 用最少的代码创建索引和搜索
    Windows Server 2008 R2 配置AD(Active Directory)域控制器
    Windows Server 2008 R2 负载平衡入门篇
    Asp.net MVC 的八个扩展点
    C# 使用memcache(memcache安装)
  • 原文地址:https://www.cnblogs.com/webxu20180730/p/11031299.html
Copyright © 2011-2022 走看看