• Vue复习三(路由)


    https://router.vuejs.org/zh/installation.html

     <router-link to="/foo">Go to Foo</router-link>
      <router-view></router-view>
    

    动态ID

    /one/:id
    this.$route.params.id
    问号传参
    this.$route.query
    

    props 拿到动态的id值

    const User = {
      props: ['id'],
      template: '<div>User {{ id }}</div>'
    }
    const router = new VueRouter({
      routes: [
        { path: '/user/:id', component: User, props: true },
    
        // 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
        {
          path: '/user/:id',
          components: { default: User, sidebar: Sidebar },
          props: { default: true, sidebar: false }
        }
      ]
    })
    

    props 被设置为 trueroute.params 将会被设置为组件属性

    函数的形式

     { path: '/search', component: SearchUser, props: (route) => ({ query: route.query})
      
      props:['query']
      
      ?name=333
      this.query
      // {name:333}
    

    响应路由的变化

    watch:{
                $route(to, from) {
                    // 现在的, 之前的
                    console.log(to, from);
                }
            },
    

    匹配条件

    	// 匹配所有路径
      path: '*'
    路由导航
    // 给出一个路由 { path: '/user-*' }
    this.$router.push('/user-admin')
    this.$route.params.pathMatch // 'admin'
    
    可选
    /optional-params/:foo?
    案例
    /optional-params
    /optional-params/foo
    
    限定id的条件
    // 一个参数后面可以跟一个正则表达式模式的括号
    //只有当:id为所有数字时,该路由才会匹配
    /params-with-regex/:id(\d+)
    也就是id只有是数字的时候才能匹配
                             
    // 星号可以匹配任何东西
     { path: '/asterisk/*' }      
     // 括号中的内容是可选的                      
    /optional-group/(foo/)?bar
    

    嵌套路由

      routes: [
        { path: '/user/:id', component: User,
            children: [
            {
              // 相对的跟angular类似
                path:'posts'
              component: UserProfile
            },
       ]}
          
    

    编程式导航

    声明式 编程式
    <router-link :to="..."> router.push(...)
    // 字符串, 绝对的
    router.push('home')
    
    // 对象的形式是相对的, 如果是'two/three' => 'two/three'
    router.push({ path: 'home' })
    // 问好传参
    router.push({path:'/two/three',query:{age:'gsg'}})
    

    替换

    替换掉当前的 history 记录

    声明式 编程式
    <router-link :to="..." replace> router.replace(...)

    退后,前进

    类似 window.history.go(n)

    // 后退一步记录,等同于 history.back()
    router.go(-1)
    // 在浏览器记录中前进一步,等同于 history.forward()
    router.go(1)
    

    Vue Router 的导航方法 (pushreplacego)

    在各类路由模式 (historyhashabstract) 下表现一致。

    router.push(location, onComplete?, onAbort?)
    router.push(location).then(onComplete).catch(onAbort)
    router.replace(location, onComplete?, onAbort?)
    router.replace(location).then(onComplete).catch(onAbort)
    router.go(n)
    router.back()
    router.forward()
    

    命名视图

    就是多视图

    案例

       <router-view></router-view>
       <router-view name="three"></router-view>
    
    		 {
                    path: 'three/:id',
                    components: {
                        default:()=>import('@/components/FourChild.vue'),
                        three:()=>import('@/components/ThreeChild.vue')
                    }
                }
    

    路由点击多次报错

    禁止全局的路由错误处理

    const originalPush = VueRouter.prototype.push
    VueRouter.prototype.push = function push (location) {
        return originalPush.call(this, location).catch(err => err)
    } 
    

    命名路由

    就是不用写那么多配置,快捷的跳转

    const router = new VueRouter({
      routes: [
        {
          path: '/user/:userId',
          name: 'user',// 快捷跳转方式
          component: User
        }
      ]
    })
    
    html跳转方式
    <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
    // 命名的路由
    router.push({ name: 'user', params: { userId: '123' }})
    如果你想独立显示的,就单独写一个吧
    

    重定向

     { path: '/a', redirect: '/b' }
    // 快捷重定向到命名路由
    { path: '/a', redirect: { name: 'foo' }}
    //方法
       { path: '/a', redirect: to => {
          // 方法接收 目标路由 作为参数
          // return 重定向的 字符串路径/路径对象
        }}
    

    别名

    { path: '/a', component: A, alias: '/b' }
    
    /a 的别名是 /b
    就是/b 访问的也是 /a 但是当前地址也是/b 本来不变, 类似一个别名
    

    History 模式

    默认hash模式, 设置history前台后台就需要配置

    路由守卫

    全局前置守卫 beforeEach

    当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中

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

    to: Route: 即将要进入的目标

    from: Route: 当前导航正要离开的路由

    next:Function

    • next() 进行管道中的下一个钩子

    • next(false) 中断当前导航

    • next('/') 或者next({path:'/'}) 跳转到不同的地址

      replace: true
      name: 'home' 比较自由
      
    • next(error) 报错了, 会把错误传递到router.onError() 注册回调

    next() 严格上调用一次

    router.beforeEach((to, from, next) => {
      if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
      else next()
    })
    

    路由独享的守卫 beforeEnter

    const router = new VueRouter({
      routes: [
        {
          path: '/foo',
          component: Foo,
          beforeEnter: (to, from, next) => {
            // ...
          }
        }
      ]
    })
    

    组件内的守卫

    {
        data(){
            return {
                
            }
        },
      beforeRouteEnter (to, from, next) {
        // 在渲染该组件的对应路由被 confirm 前调用
        // 不!能!获取组件实例 `this`
        // 因为当守卫执行前,组件实例还没被创建
      },
      beforeRouteUpdate (to, from, next) {
        // 在当前路由改变,但是该组件被复用时调用
        // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
        // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
        // 可以访问组件实例 `this`
      },
      beforeRouteLeave (to, from, next) {
        // 导航离开该组件的对应路由时调用
        // 可以访问组件实例 `this`
      } 
    }
    

    传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。

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

    这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消

    beforeRouteLeave (to, from, next) {
      const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
      if (answer) {
        next()
      } else {
        next(false)
      }
    }
    

    全局解析守卫 beforeResolve

    在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后

    全局后置钩子

    注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身

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

    导航解析流程

    默认

    • beforeEach 全局前置守卫(登录)
      • beforeEnter 路由独享的守卫
        • beforeRouteEnter 组件内守卫(当守卫执行前)
        • beforeRouteUpdate 组件内复用守卫(:id /1 /2)
        • beforeRouteLeave 离开守卫,例如未保存
    • beforeResolve 全局解析守卫
    • afterEach 全局后置钩子

    router.onError

    router.onError(error=>{
        console.log(error)
    })
    

    注册一个回调,该回调会在路由导航过程中出错时被调用。注意被调用的错误必须是下列情形中的一种:

    • 错误在一个路由守卫函数中被同步抛出;
    • 错误在一个路由守卫函数中通过调用 next(err) 的方式异步捕获并处理;
    • 渲染一个路由的过程中,需要尝试解析一个异步组件时发生错误。

    元数据 meta

        {
              path: 'bar',
              component: Bar,
              // a meta field
              meta: { requiresAuth: true }
        }
    
    this.$route.meta
    // { requiresAuth: true }
    

    过渡

    <transition>
      <router-view></router-view>
    </transition>
    
    动态的
    当前路由与目标路由的变化关系,
    <!-- 使用动态的 transition name -->
    <transition :name="transitionName">
      <router-view></router-view>
    </transition>
    
    // watch $route 决定使用哪种过渡
    watch: {
      '$route' (to, from) {
        const toDepth = to.path.split('/').length
        const fromDepth = from.path.split('/').length
        this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
      }
    }
    

    数据获取

    导航完成后获取数据

      data () {
        return {
          loading: false
        }
      },
      created () {
        // 当视图被创建并且数据被创建时,获取数据
        this.fetchData()
      },
      watch: {
        // 如果路由发生变化,再次调用该方法
        '$route': 'fetchData'
      },
      methods: {
          // 数据请求
        fetchData () {
        }
      }
    

    导航前获取

    就使用 路由组件内守卫进行操作

    滚动

    自定义滚动

    scrollBehavior函数接收tofrom路由对象。第三个参数,savedPosition仅在通过popstate导航(由浏览器的后退/前进按钮触发)时才可用。也是history 模式

    const router = new VueRouter({
      routes: [...],
      scrollBehavior (to, from, savedPosition) {
        // 返回对象 { x: number, y: number }
           return { x: 0, y: 0 }      
         
      }
    })
    

    滚动到锚点

    scrollBehavior (to, from, savedPosition) {
      if (to.hash) {
        return {
          selector: to.hash
        }
      }
    }
    

    平滑滚动

    scrollBehavior (to, from, savedPosition) {
      if (to.hash) {
        return {
          selector: to.hash,
          behavior: 'smooth',
        }
      }
    }
    

    异步滚动

    scrollBehavior (to, from, savedPosition) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve({ x: 0, y: 0 })
        }, 500)
      })
        
        500ms 后滚动
    

    延迟加载路线

    const Foo = () => import('./Foo.vue')
    { path: '/foo', component: Foo }
    

    将同一块中的组件分组

    命名块

    const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
    const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
    const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
    

    *导航失败

    3.4.0 新功能

    使用router-link组件时,这些故障均不会记录错误

    有点蒙蔽, 不太懂

    router-link

    <!-- 字符串 -->
    <router-link to="home">Home</router-link>
    <!-- 绑定数据 -->
    <router-link :to="'home'">Home</router-link>
    <!-- 命名的路由 -->
    									<!-- 动态ID :userId 的值-->
    <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 替换

    <router-link :to="{ path: '/abc'}" replace></router-link>
    

    append 相对

    设置 append 属性后,则在当前 (相对) 路径前添加基路径

    本来  /one/1
    跳转后   /one/2
    <router-link :to="{ path: 2}" append></router-link>
    

    tag 更改标签名

    <router-link to="/foo" tag="li">foo</router-link>
    <!-- 渲染结果 -->
    <li>foo</li>
    

    active-class 激活的路由class

    • 类型: string
    • 默认值: "router-link-active"
     <router-link :to="{path:'2'}"  active-class="aaa">222</router-link>
    

    axact 完全匹配

    <!-- 这个链接只会在地址为 / 的时候被激活 -->
    <router-link to="/" exact></router-link>
    

    event 事件促发的条件

    • 类型: string | Array<string>
    • 默认值: 'click'

    可以是一个字符串或是一个包含字符串的数组

    <router-link :to="{path:1}"  tag="input" event="blur">
        222
    </router-link>
    改成input 失去焦点触发
    

    exact-active-class 精准匹配class

    router-view

    <transition>
      <keep-alive>
        <router-view></router-view>
      </keep-alive>
    </transition>
    

    name 用于命名视图

    Router

    routes

    interface RouteConfig = {
      path: string,
      component?: Component,
      name?: string, // 命名路由
      components?: { [name: string]: Component }, // 命名视图组件
      redirect?: string | Location | Function,
      props?: boolean | Object | Function,
      alias?: string | Array<string>,
      children?: Array<RouteConfig>, // 嵌套路由
      beforeEnter?: (to: Route, from: Route, next: Function) => void,
      meta?: any,// 元数据
    
      // 2.6.0+
      caseSensitive?: boolean, // 匹配规则是否大小写敏感?(默认值:false)
      pathToRegexpOptions?: Object // 编译正则的选项
    }
    

    外部的配置

     new VueRouter({
        routes,
         // 下面都是全局
        mode:'history',
        base:'/app/sex/' // 前缀
         // 默认的激活的class   默认值: "router-link-exact-active"
    	linkActiveClass:'ccc'
         // 默认精确激活的class 默认值: "router-link-exact-active"
         linkExactActiveClass:"aaa"
    
    })
    
    

    parseQuery / stringifyQuery

    提供自定义查询字符串的解析/反解析函数。覆盖默认行为。

    其实提供这两种用法,是针对问号传参进行加密解决的作用

    https://www.codenong.com/cs107092308/

    
    // https://github.com/ljharb/qs
    import qs from 'qs';
    
    const router = new Router({
        routes: [
            // ...
        ],
        // 反序列化
        parseQuery(query) {
            return qs.parse(query);
        },
        //序列化
        stringifyQuery(query) {
            var result = qs.stringify(query);
    
            return result ? ('?' + result) : '';
        }
    });
    

    router.app vue实例

    // 拿到vue 实例
        console.log(this.$router.app);
    

    router.currentRoute 当前路由信息对象

        console.log(this.$router.currentRoute);
    

    ## router.getMatchedComponents 当前路由匹配的组件数组

    通常在服务端渲染的数据预加载时使用

    全局后置路由守卫
    router.beforeResolve((to, from, next) => {
       // 拿到当前匹配的数组
        console.log(router.getMatchedComponents(to));
        next()
    })
    

    路由对象Route

    // 当前路由的路径,总是解析绝对路径
    $route.path
    // 动态ID
    $route.params
    // 问号传参
    $route.query
    // hash
    $route.hash
    // 解析后URL,包括查询参数和hash的完整路径
    $route.fullPath
    // 一个包含从上到下的所有对象 (副本)   又叫路由记录
    $route.matched
    // 当前路由的名称, 命名路由
    $route.name
    // 如果存在重定向,即为重定向来源的路由的名字, (别名还想也可以)
    $route.redirectedFrom
    

    决定自己的高度的是你的态度,而不是你的才能

    记得我们是终身初学者和学习者

    总有一天我也能成为大佬

  • 相关阅读:
    【LibreOJ】#6257. 「CodePlus 2017 12 月赛」可做题2
    【Atcoer】ARC088 E
    【Atcoder】ARC088 D
    【CodeForces】671 D. Roads in Yusland
    【CodeForces】671 B. Robin Hood
    【CodeForces】671 C. Ultimate Weirdness of an Array
    【CodeForces】679 A. Bear and Prime 100
    【CodeForces】679 B. Bear and Tower of Cubes
    【BZOJ】3262: 陌上花开
    【CodeForces】899 F. Letters Removing
  • 原文地址:https://www.cnblogs.com/fangdongdemao/p/14398123.html
Copyright © 2020-2023  润新知