zoukankan      html  css  js  c++  java
  • 安装 / 初始化 / 路由记录

    安装

    • 在 Vue 后面加载 vue-router,它会自动安装的
    <script src="/path/to/vue.js"></script>
    <script src="/path/to/vue-router.js"></script>
    
    • 如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装路由功能
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    Vue.use(VueRouter)
    

    ——————————————————————————————————————————————————————————

    初始化(Router 构建选项)

    • 使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 Vue Router 添加进来,我们需要做的是,将组件 (components) 映射到路由 (routes),然后告诉 Vue Router 在哪里渲染它们
    <div id="app">
      <h1>Hello App!</h1>
      <p>
        <!-- 使用 router-link 组件来导航. -->
        <!-- 通过传入 `to` 属性指定链接. -->
        <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
        <router-link to="/foo">Go to Foo</router-link>
        <router-link to="/bar">Go to Bar</router-link>
      </p>
      <!-- 路由出口 -->
      <!-- 路由匹配到的组件将渲染在这里 -->
      <router-view></router-view>
    </div>
    
    // 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)
    
    // 1. 定义 (路由) 组件。
    // 可以从其他文件 import 进来
    const Foo = { template: '<div>foo</div>' }
    const Bar = { template: '<div>bar</div>' }
    
    // 2. 定义路由
    // 每个路由应该映射一个组件。 其中"component" 可以是
    // 通过 Vue.extend() 创建的组件构造器,(依据配置文件生成vue的子类)
    // 或者,只是一个组件配置对象。(配置文件有4种方式获得方式,1种同步,3种异步,详见vue的注册组件 / 插件)
    // 我们晚点再讨论嵌套路由。
    const routes = [
      { path: '/foo', component: Foo },
      { path: '/bar', component: Bar }
    ]
    
    // 3. 创建 router 实例,然后传 `routes` 配置
    // 你还可以传别的配置参数, 不过先这么简单着吧。
    const router = new VueRouter({
      routes // (缩写) 相当于 routes: routes
    })
    
    // 4. 创建和挂载根实例。
    // 记得要通过 router 配置参数注入路由,
    // 从而让整个应用都有路由功能
    const app = new Vue({
      router
    }).$mount('#app')
    

    ————————————————————————————————————————————————————

    • 定义路由具有以下配置项routes(匹配路径、对应组件、命名、重定向、原信息、嵌套路由)、mode(路由模式)、base(基路径)、linkActiveClass(默认“激活 class 类名”)、linkExactActiveClass(精确激活的默认的 class)、scrollBehavior(滚动位置复原)、parseQuery / stringifyQuery(查询字段解析)、fallback(自动回退到 hash 模式)

    routes

    declare type 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; // 编译正则的选项
    }
    

    path路径

    • 有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果,参数值会被设置到 this.$route.params
    const router = new VueRouter({
      routes: [
        // 动态路径参数 以冒号开头
        { path: '/user/:id', component: User }    // 像 /user/foo 和 /user/bar 都将映射到相同的路由
      ]
    })
    
    ...
    template: '<div>User {{ $route.params.id }}</div>'    // id由路由中的:后接字符串决定
    ...
    
    • 可以在一个路由中设置多段“路径参数”,对应的值都会设置到 $route.params 中。
    /user/:username    // 匹配/user/evan    // $route.params === { username: 'evan' }
    /user/:username/post/:post_id    // 匹配/user/evan/post/123    // $route.params === { username: 'evan', post_id: 123 } 
    
    • 路由采用/间隔来进行一一对应,例如path: '/about/:id1/second'匹配不到url为/about/1/2/second的路径
    • 路由根据routes数组中的顺序由前向后匹配,以第一个符合值为准
    • 当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
    • 复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route 对象,或者使用 2.2 中引入的 beforeRouteUpdate 导航守卫
    • 使用 path-to-regexp 作为路径匹配引擎,所以支持很多高级的匹配模式,例如:可选的动态路径参数、匹配零个或多个、一个或多个,甚至是自定义正则匹配。
      • { path: '/optional-params/:foo?' }参数/:foo可有可无,可以匹配到/optional-params
      • { path: '/params-with-regex/:id(\d+)' }参数id必须满足d+这个正则表达式,注意这个正则表达式需要转义所以要写为\
      • { path: '/asterisk/*' }可以匹配多个分割的路径,例如/asterisk/foo/asterisk/foo/bar,同理{ path: '*' }可以匹配任意路径,用于放置在数组最后,处理匹配不到任何路由的情况
      • { path: '/optional-group/(foo/)?bar' }路由的部分节点可有可无,例如可以匹配/optional-group/bar/optional-group/foo/bar

    component

    • 其中"component" 可以是通过 Vue.extend() 创建的组件构造器,(依据配置文件生成vue的子类)或者,只是一个组件配置对象。(配置文件有4种方式获得方式,1种同步,3种异步,详见vue的注册组件 / 插件)
    • 路由懒加载{ path: '/foo', component: () => import('./Foo.vue') }需要添加 syntax-dynamic-import 插件,才能使 Babel 可以正确地解析语法。
    • 异步组件定义为返回一个 Promise 的工厂函数 (该函数返回的 Promise 应该 resolve 组件本身):{ path: '/foo', component: () => Promise.resolve({ /* 组件定义对象 */ }) }
    • 想把某个路由下的所有组件都打包在同个异步块 (chunk) 中。只需要使用 命名 chunk,一个特殊的注释语法来提供 chunk name (需要 Webpack > 2.4)。

    name命名路由

    • name命名路由,用于路由跳转(不需要路径直接依据name名跳转)
    const router = new VueRouter({
      routes: [
        {
          path: '/user/:userId',
          name: 'user',
          component: User
        }
      ]
    })
    
    router.push({ name: 'user', params: { userId: 123 }})
    <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
    

    components命名视图

    • 命名视图:同时 (同级) 展示多个视图。如果 router-view 没有设置名字,那么默认为 default。命名视图没有对应命名组件时不会被渲染
    <router-view class="view one"></router-view>
    <router-view class="view two" name="a"></router-view>
    <router-view class="view three" name="b"></router-view>
    
    const router = new VueRouter({
      routes: [
        {
          path: '/',
          components: {
            default: Foo,
            a: Bar,
            b: Baz
          }
        }
      ]
    })
    
    

    redirect重定向

    • 重定向。导航守卫并没有应用在跳转路由上,例如为 /a 路由添加一个 beforeEach 或 beforeLeave 守卫并不会有任何效果。
    const router = new VueRouter({
      routes: [
        { path: '/a', redirect: '/b' } 
      ]
    })
    
    // 重定向的目标也可以是一个命名的路由:
    const router = new VueRouter({
      routes: [
        { path: '/a', redirect: { name: 'foo' }}
      ]
    })
    
    // 一个方法,动态返回重定向目标:
        { path: '/dynamic-redirect/:id?',
          redirect: to => {
            const { hash, params, query } = to
            if (query.to === 'foo') {
              return { path: '/foo', query: null }
            }
            if (hash === '#baz') {
              return { name: 'baz', hash: '' }
            }
            if (params.id) {
              return '/with-params/:id'
            } else {
              return '/bar'
            }
          }
        },
    
    // 其中的参数可以传递
    { path: '/redirect-with-params/:id', redirect: '/with-params/:id' },
    

    props传参

    • 在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。使用 props 将组件和路由解耦:
    // 如果同时存在:id和props传入id,哪个优先级高些?怀疑是组件的传入值更高些
    const User = {
      props: ['id'],
      template: '<div>User {{ id }}</div>'
    }
    const router = new VueRouter({
      routes: [
        { path: '/user/:id', component: User, props: true },    // 如果 props 被设置为 true,route.params 将会被设置为组件属性。布尔值的方式并不灵活,要求props和:id要做到名称一一对应,不然就会绑定到根元素上失去意义
    
        // 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
        {
          path: '/user/:id',
          components: { default: User, sidebar: Sidebar },
          props: { default: true, sidebar: false }
        }
      ]
    })
    
    // 可以在路由中设置props的值,例如
    { path: '/static', component: Hello, props: { name: 'world' }},    // 这时,props.name === ‘world’ 
    
    // 你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等。
    const router = new VueRouter({
      routes: [
        { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) } 
      ]
    })
    
    // 包含命名视图时传入props的值
        {
          path: '/',
          name: 'home',
          components: {
            default: HelloWorld1,
            sidebar: HelloWorld2
          },
          props: {
            default: {
              msg: 'default'
            },
            sidebar: {
              message: 'sidebar'
            }
          }
        },
    
    • 请尽可能保持 props 函数为无状态的(指在多个函数之间是否存在上下文关系,即当前函数的运行结果会受其他函数运行结果影响),因为它只会在路由发生变化时起作用。如果你需要状态来定义 props,请使用包装组件(可能是指用一个父组件包裹要共用的数据,然后通过props传入每个子组件中,而不是通过路由的props函数实现传递),这样 Vue 才可以对状态变化做出反应。
    • 上面这条说明了普通props和路由props的区别,普通props可以实现响应式数据传入,但是路由props只有当路由改变时才会改变传入值

    alias别名

    • 别名会使用a的组件,但url依然保持使用b的。“别名”的功能让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构。比如:原先路径为/a/b,/a渲染了父组件,/b渲染了嵌套在父组件中的<router-view>,设置了嵌套路由后可以用/c来直接访问这个嵌套关系的路由
    const router = new VueRouter({
      routes: [
        { path: '/a', component: A, alias: '/b' }
      ]
    })
    
    // 高级用法
        { path: '/home', component: Home,
          children: [
            // absolute alias
            { path: 'foo', component: Foo, alias: '/foo' },    // 不仅当前/级别可以设置别名,还可以从根级别开始设置例如
            // relative alias (alias to /home/bar-alias)
            { path: 'bar', component: Bar, alias: 'bar-alias' },    // 当前级别的别名
            // multiple aliases
            { path: 'baz', component: Baz, alias: ['/baz', 'baz-alias'] }    // 多个别名
          ]
        }
    

    children嵌套

    • 嵌套路由的父级必须指向一个有<router-view>视图容器的组件。仅仅要实现路由名称嵌套应该使用base设置基路由
    • 要在嵌套的出口中渲染组件,需要在 VueRouter 的参数中使用 children 配置
    const router = new VueRouter({
      routes: [
        { path: '/user/:id', 
          component: User,    // User组件中存在一个<router-view>用于渲染children匹配到的组件
          children: [
            {
              // 当 /user/:id/profile 匹配成功,
              // UserProfile 会被渲染在 User 的 <router-view> 中
              path: 'profile',
              component: UserProfile
            },
            {
              // 当 /user/:id/posts 匹配成功
              // UserPosts 会被渲染在 User 的 <router-view> 中
              path: 'posts',
              component: UserPosts
            }
          ]
        }
      ]
    })
    
    // 可以通过设置children下path为''来匹配路径仅仅为父路径时
    ...
    {
        path: '/user/:id', 
        component: User,
        children: [
            { path: '', component: UserHome },    // 依据上例,路径为/user/:id时,User组件内的&lt;router-view>渲染UserHome 组件
        ]
    }
    ...
    
    • 路由记录可以是嵌套的,因此,当一个路由匹配成功后,他可能匹配多个路由记录。一个路由匹配到的所有路由记录会暴露为 $route 对象的 $route.matched 数组
    const router = new VueRouter({
      routes: [
        {    // 父路由记录
          path: '/foo',    
          component: Foo,
          children: [
            {    // 子路由记录
              path: 'bar',    
              component: Bar,
              // a meta field
              meta: { requiresAuth: true }
            }
          ]
        }
      ]
    })
    

    beforeEnter

    • 路由级守卫,详见导航守卫

    meta元信息

    • 配置
    ...
    path: 'salary/substitutingPayroll/process/:processId',
    meta: {
        checkCallBackUrl: '/salary/ihr/salary/substitutingPayroll/processDetail/'
    }
    ...
    
    • 路由元信息,一般和路由全局的 beforeEach 守卫配合,用于判断是否需要判断登录状态及是否登录
    router.beforeEach((to, from, next) => {    // to.matched一个数组,包含当前路由的所有嵌套路径片段的路由记录 。
      if (to.matched.some(record => record.meta.requiresAuth)) {    // meta.requiresAuth设置了该路由是否需要检验登录状态
        if (!auth.loggedIn()) {
          next({
            path: '/login',
            query: { redirect: to.fullPath }
          })
        } else {
          next()
        }
      } else {
        next() // 确保一定要调用 next()
      }
    })
    

    ————————————————————————————————————————————————————

    mode

    • 默认值: "hash" (浏览器环境) | "abstract" (Node.js 环境)

    • 可选值: "hash" | "history" | "abstract"

      • hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。(url中“#”部分开始的都是hash)
      • history: 依赖 HTML5 History API 和服务器配置。
      • abstract: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。
    • history 模式需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就不好看了。

    • 这么做以后,你的服务器就不再返回 404 错误页面,因为对于所有路径都会返回 index.html 文件。为了避免这种情况,你应该在 Vue 应用里面覆盖所有的路由情况,然后在给出一个 404 页面。

    const router = new VueRouter({
      mode: 'history',
      routes: [
        { path: '*', component: NotFoundComponent }    // 添加在最后
      ]
    })
    

    base

    • 默认值: "/"
    • 应用的基路径。例如,如果整个单页应用服务在 /app/ 下,然后 base 就应该设为 "/app"。
    • 设置了基路由后<router-link to="/">Home</router-link>实际跳转的是基路由/这个页面
    • 设置的基路由在route对象中是无法获得的,不管是fullPath还是path都只包含匹配的路由
    • 通过设置基路由实现的路由嵌套能够自动实现根路由别名,例如(在@vue/cli创建的多页面应用中观察所得)
    export default new Router({
      mode: 'history',
      base: `${process.env.BASE_URL}index`,
      routes: [
        {
          path: '/',
          name: 'home',
          component: Home
        },
        {
          path: '/about',    //  该路由可以通过 http://localhost:8080/index/about 访问,也可以通过 http://localhost:8080/about 访问
          name: 'about',
          // route level code-splitting
          // this generates a separate chunk (about.[hash].js) for this route
          // which is lazy-loaded when the route is visited.
          component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
        }
      ]
    })
    

    linkActiveClass

    • 有部分路径匹配时
    • 默认值: "router-link-active"
    • 全局配置 <router-link> 的默认“激活 class 类名”。

    linkExactActiveClass

    • 全路径匹配时,包括#、?部分也要完全匹配
    • 默认值: "router-link-exact-active"
    • 全局配置 <router-link> 精确激活的默认的 class。

    scrollBehavior

    • tofrom 都是路由对象

    • 这个方法要求返回如下几种对象之一:

      • { x: number, y: number } 例如return { x: 0, y: 0 }滚动到页面顶部
      • { selector: string, offset? : { x: number, y: number }} (offset 只在 2.6.0+ 支持) 例如return { selector: to.hash }滚动到锚点,offset应该是相对锚点的偏移量(to.hash以#开头)
      • 如果返回一个 falsy (falsy 不是 false)的值,或者是一个空对象,那么不会发生滚动。
      • 也可以返回一个 Promise 来得出预期的位置描述
    • 第三个参数 savedPosition 当且仅当 popstate 导航 (通过浏览器的 前进/后退 按钮触发) 时才可用。应该是代表前进/后退目标页面的滚动位置可以这样使用return savedPosition。这个功能只在支持 history.pushState 的浏览器中可用。(history.pushState把url写入history,但是不会触发重新加载页面)

    const router = new VueRouter({
      routes: [...],
      scrollBehavior (to, from, savedPosition) {
        // return 期望滚动到哪个的位置
      }
    })
    
    // 返回一个 Promise
    scrollBehavior (to, from, savedPosition) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve({ x: 0, y: 0 })
        }, 500)
      })
    }
    
    • 将其挂载到从页面级别的过渡组件的事件上,令其滚动行为和页面过渡一起良好运行是可能的。但是考虑到用例的多样性和复杂性,我们仅提供这个原始的接口,以支持不同用户场景的具体实现。

    parseQuery / stringifyQuery

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

    fallback

    • 当浏览器不支持 history.pushState 控制路由是否应该回退到 hash 模式。默认值为 true。在 IE9 中,设置为 false 会使得每个 router-link 导航都触发整页刷新。它可用于工作在 IE9 下的服务端渲染应用,因为一个 hash 模式的 URL 并不支持服务端渲染。
  • 相关阅读:
    DB2隔离级别之RR/RS/CS/UR
    struts1之工作原理
    CSS之伪类
    JSF+EJB+JPA之整体思想
    microservice-cloud-03-provider-product-8001
    在SpringCloud中MAVEN配置文件中的更改
    springBoot和MyBatis整合中出现SpringBoot无法启动时处理方式
    使用springBoot和mybatis整合时出现如下错误:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)解决方案
    application.properties
    springboot
  • 原文地址:https://www.cnblogs.com/qq3279338858/p/10302031.html
Copyright © 2011-2022 走看看