vue-router

官网:https://router.vuejs.org/zh-cn/

因为我们更多的是利用vue+webpack搭建整个项目的框架(例如vue-cli),所以我们这里利用vue-cli讲解

1.路由的介绍

  • 何为前端路由

    1. 路由是根据不同的url展示不同的页面或内容
    2. 前端路由就是把不同路由对应不同内容或者页面的任务放在钱前端,以前是服务端根据不同的url返回不同的内容
  • 何时使用前端路由

    1. 单页面应用,大部分页面节后不变,只是改变内容
  • 前端路由优点

    1. 用户体验好,不用每一次都从后台全部获取,快速展示给用户
  • 前端路由缺点

    1. 不利于SEO
    2. 利用浏览器的前进和后退键的时候回重新发请求,没有有效的利用缓存
    3. 单页面应用没有办法记住用户上一个页面的滚动位置,假如用户将A页面向下滚1屏,跳转到B再倒退回A时,A页面会从头开始,而不是上次看到的1屏幕的位置

2.vue-router入门

用 Vue.js + vue-router 创建单页应用很常用,vue-router 用来搭建路由,这里的路由并不是指我们平时所说的硬件路由器,这里的路由就是SPA(单页应用)的路径管理器。再通俗的说,vue-router就是我们WebApp的链接路径管理系统。

2.1安装

npm install vue-router --save-dev

2.2解读router配置文件

//引入Vue
import Vue from 'vue';  
//引入vue-router              
import Router from 'vue-router';
//引入根目录下的HelloWorld.vue组件
import HelloWorld from '@/components/HelloWorld';

//Vue全局使用Router
Vue.use(Router);

export default new Router({
  //配置路由,这里是个数组
  routes: [
    {                           //每一个链接都是一个对象
      path: '/',                //链接路径
      name: 'HelloWorld',       //路由名称,可以在router-link和router.push中使用,就相当于这个组件了
      component: HelloWorld     //对应的组件模板
    }
  ]
});

vue-router_第1张图片
可以看到http://localhost:8080/#/ 就是我们的根‘/’页面

2.3增加一个新的页面

  1. 在src/components目录下,新建 first.vue 文件。
  2. router/index.js文件的上边引入first组件
  3. 增加路由配置:在router/index.js文件的routes[]数组中,新增加一个对象
import Vue from 'vue';
import Router from 'vue-router';
import HelloWorld from '@/components/HelloWorld';
import First from '@/components/first';

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/first',
      name: 'First',
      component: First
    }
  ]
});

结果:
vue-router_第2张图片
可以看到http://localhost:8080/#/first 就是我们的根‘/first’页面

2.4 去掉路径中 ·#·

我们可以发现vue路径中是带有 # 号,例如: http://localhost:8080/#/first
这是因为:
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。

如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。

import Vue from 'vue';
import Router from 'vue-router';
import First from '@/components/first';

Vue.use(Router);

export default new Router({
 // 更改模式
  mode: 'history',
  routes: [
    {
      path: '/first',
      name: 'First',
      component: First
    }
  ]
});

我们利用 mode: ‘history’, 更改模式
这样一来http://localhost:8080/#/first就访问不到,需要采用http://localhost:8080/first访问

2.5 了解router和route

2.5.1$router:

  1. 在 Vue 实例内部,我们可以在任何组件内通过 this.$router 访问路由器
  2. 使用 this.$router 的原因是我们并不想在每个独立需要封装路由的组件中都导入路由。
  3. 使用 this.$router 我们可以在浏览器的history中进行操作

我们在模板文件将 this.$router打印

methods: {
    go() {
      console.log(this.$router);
    }
  },

结果
vue-router_第3张图片

具体的作用可以看后面的 6.编程式的导航

2.5.2$route

访问当前路由

我们在模板文件中将$route打印出来

methods: {
    go() {
      console.log(this.$route);
    }
  },

结果:
vue-router_第4张图片
我们可以获取$route的params和query获取到当前路由的信息

关于设置路由参数可以看下文章后面的内容

2.5.2.1$router.params

params一旦在路由中配置,params就是路由的一部分,如果在跳转的时候没有传这个参数,会导致跳转失败或者页面会没有内容。
例如我们设置路由为

 {
      path: '/first/:from/:age',
      name: 'First',
      component: First
 }

:from 和 :age 是形参,我们需要传递实参,可以通过this.route.params.[name]获取实参
vue-router_第5张图片
如果我们少一个参数,如http://localhost:8080/#/first/one 那么就是无法访问

如果我们不设置params,我们直接在url中加上,那么我们也是无法访问的

2.5.2.2router.query

query是拼接在url后面的查询参数,没有也没关系。
例如我们路由设置

var  c = china;
this.$router.push('/first?from=' + c);
  • 那么我们就可以用 http://localhost:8080/#/first?from=china 访问了,
  • 我们不加参数 http://localhost:8080/#/first 也是可以访问的
  • 多加几个参数也是可以的 http://localhost:8080/#/first?from=china&age=12

可以通过this.route.query.[name]获取

3 动态路由

我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染
在路由配置文件里以冒号的形式设置参数。动态路径参数 以冒号开头

3.1设置

import Vue from 'vue';
impimport Vue from 'vue';
import Router from 'vue-router';
import User from '@/components/User';

Vue.use(Router);

export default new Router({
  routes: [
    {
      //设置
      path: '/user/:id',
      name: 'User',
      component: User
    }
  ]
});

现在呢,像 /user/foo 和 /user/bar 都将映射到相同的路由。

3.2获取参数

this.$route.params.id

3.3设置多个路径参数

路由中可以设置多段『路径参数』,对应的值都会设置到 $route.params 中
vue-router_第6张图片

4.router-link制作导航

router-link 比起写死的 a href=”…” 会好一些,理由如下:

  1. 无论是 HTML5 history 模式还是 hash 模式,它的表现行为一致,所以,当你要切换路由模式,或者在 IE9 降级使用
    hash 模式,无须作任何变动。
  2. 在 HTML5 history 模式下,router-link 会守卫点击事件,让浏览器不再重新加载页面。
  3. 当你在 HTML5 history 模式下使用 base 选项之后,所有的 to 属性都不需要写(基路径)了。

4.1参数 to

例如:

    
    
    <router-link to="/foo">Go to Foorouter-link>
  • to:是我们的导航路径,要填写的是你在router/index.js文件里配置的path值,如果要导航到默认首页,只需要写成
    to=”/”
  • [显示字段] :就是我们要显示给用户的导航名称,比如首页 新闻页。

当被点击后,内部会立刻把 to 的值传到 router.push(),直接写string表示根路径


<router-link to="home">Homerouter-link>

<a href="home">Homea>


<router-link v-bind:to="'home'">Homerouter-link>


<router-link :to="'home'">Homerouter-link>


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


<router-link :to="{ name: 'user', params: { userId: 123 }}">Userrouter-link>


<router-link :to="{ path: 'register', query: { plan: 'private' }}">Registerrouter-link>

如果 router-link to指向path,params 会被忽略

路径还是/user   不是/uer/123
:to="{ path: 'user', params: { userId: 123 }}">User

例如

路由配置文件中引入组件:

{
      path: '/first',
      name: 'FirstVue',
      component: First
}

跳转

:to="{ name: 'FirstVue', params: { userId: 123 }}">FirstVue

4.2参数replace

设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录。

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

4.3参数append

设置 append 属性后,则在当前(相对)路径前添加基路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b

<router-link :to="{ path: 'relative/path'}" append></router-link>

4.4参数tag

有时候想要 router-link渲染成某种标签,例如 li。 于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航。

<router-link to="/foo" tag="li">foorouter-link>

<li>fooli>

4.5点击时自动加class

当router-link被激活时,或自动加上 class属性名:router-link-active
链接激活时使用的 CSS 类名。默认值可以通过路由的构造选项 linkActiveClass 来全局配置。

4.6将激活 class 应用在外层元素

有时候我们要让激活 class 应用在外层元素,而不是 a 标签本身,那么可以用 router-link 渲染外层元素,包裹着内层的原生 a标签:

<router-link tag="li" to="/foo">
  <a>/fooa>
router-link>

在这种情况下,a 将作为真实的链接(它会获得正确的 href 的),而 “激活时的CSS类名” 则设置到外层的 li。

5.嵌套路由

就是路由器嵌套路由

  1. 新建两个组件模板 first-one.vue 和 first-two.vue
  2. 把first.vue改成一个通用的模板,加入 router-view 标签,给子模板提供插入位置。first-one.vue 和 first-two.vue
    都相当于first.vue的子页面
  3. 在路由的配置文件中配置

first.vue:

<p>导航 :
   <router-link to="/first/one">one首页router-link>
   <router-link to="/first/two">two页面router-link>
p>


<router-view>router-view>

注意这里的router-link 的to要写真实路径,不能直接写/[name]
router配置文件

import Vue from 'vue';
import Router from 'vue-router';
import HelloWorld from '@/components/HelloWorld';
import First from '@/components/first';
import firstOne from '@/components/first-one';
import firstTwo from '@/components/first-two';

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/first',
      name: 'First',
      component: First,
      // 设置子路由
      children: [
        {
          // 不能加‘/’,不然就变为根路径了   
          path: 'one',                             
          name: 'firstOne',
          component: firstOne
        },
        {
          path: 'two',
          name: 'firstTwo',
          component: firstTwo
        }
      ]
    }
  ]
});

其实就是在父路由下面加一个children,但是注意不要加‘/’,不然就变为根路径了 ,子路径会自动继承父路径,例如’
http://localhost:8080/#/first/one
vue-router_第7张图片
http://localhost:8080/#/first/two
vue-router_第8张图片

6.编程式的导航(router应用)

关于$router 请看前面. 2.3router

6.1 router.push

想要导航到不同的 URL,使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。
这里写图片描述

router.push(location, onComplete?, onAbort?)

该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:

// 字符串  (会直接跳到根路径,/home)
router.push('home')

// 对象
router.push({ path: 'home' })

// 命名的路由,这里的name是路径配置中你自己起的名字
router.push({ name: 'user', params: { userId: 123 }})

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

注意:
如果提供了 path,params 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 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: '/first',
      name: 'FirstVue',
      component: First
}

点击跳转:

 <button @click="go">button>
methods: {
    go() {
      this.$router.push({name: 'FirstVue',params: {userId});
    }
  },

6.2 router.replace

跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
这里写图片描述

6.3 router.go(n)

这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)

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

// 后退一步记录,等同于 history.back()
router.go(-1)

// 前进 3 步记录
router.go(3)

// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)

7.命名视图(基本上很少用到)

有时候想同时(同级)展示多个视图,而不是嵌套展示.

例如创建一个布局,有 sidebar(侧导航) 和 main(主内容) 两个视图,

一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components 配置(带上 s):

import Vue from 'vue';
import Router from 'vue-router';
import HelloWorld from '@/components/HelloWorld';
import Left from '@/components/left';
import Right from '@/components/right';

Vue.use(Router);

export default new Router({
  model: 'history',
  routes: [
    {
      path: '/',
      name: 'welcom',
      components:  {
        default: HelloWorld,
        letVue: Left,
        rightVue: Right,
      }
    }
  ]
});

在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default。

<router-view >router-view>
<router-view  name="letVue">router-view>
<router-view  name="rightVue">router-view>

8.重定向和别名

8.1重定向

『重定向』的意思是,当用户访问 /a时,URL 将会被替换成 /b,然后匹配路由为 /b

路由配置文件中(/src/router/index.js)把原来的component换成redirect参数就可以了
下面例子是从 / hello 重定向 / first, 重定向的目标也可以是一个命名的路由比如/addiress重定向 / first。

export default new Router({
  routes: [
    {
      path: '/first',
      name: 'firstVue'
      component: first
    },
    {
      path:'/hello',
      redirect:'/'
    },
    {
      path:'/addiress',
      redirect: {
        name: 'firstVue'
      }
     //或者
     //redirect: '/first'
    }
  ]
})

8.2别名

/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样

export default new Router({
  routes: [
    {
      path: '/first',
      name: 'FirstVue',
      component: First,
      alias: '/hcd'
    }
  ]
});

利用alias 设置别名’/hcd‘

结果:
http://localhost:8080/#/hcd 和 http://localhost:8080/#/first访问的是同一个页面
vue-router_第9张图片
vue-router_第10张图片

9. 404页面设置

import Vue from 'vue';
import Router from 'vue-router';
import ErrorVue from '@/components/ErrorVue';

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '*',
      name: 'Error',
      component: ErrorVue
    }
  ]
});

将path设置为 * 代表所有找不到的页面

10. 路由中的钩子

10.1路由配置文件中的钩子函数

我们只能使用beforeEnter,也就是该路径加载时触发
三个参数:

  1. to:路由将要跳转的路径信息,信息是包含在对像里边的。
  2. from:路径跳转前的路径信息,也是一个对象的形式。
  3. next:路由的控制参数,常用的有next(true)和next(false)。
import Vue from 'vue';
import Router from 'vue-router';
import HelloWorld from '@/components/HelloWorld';
import First from '@/components/first';

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/first',
      name: 'FirstVue',
      component: First,
      beforeEnter: (to, from, next) => {
        console.log('我们来到了first页面');
        console.log('to:', to);
        console.log('from:', from);
        next();
      }
    }
  ]
});

假如我们是由 ‘/’到’/first’
结果:
vue-router_第11张图片

10.2写在模板中的钩子函数

在模板中就可以有两个钩子函数可以使用:

beforeRouteEnter:在路由进入前的钩子函数。
beforeRouteLeave:在路由离开前的钩子函数。
参数和上面的beforeEnter是一样的

export default {
  name: 'params',
  data () {
    return {
      msg: 'params page'
    }
  },
  beforeRouteEnter:(to,from,next)=>{
    console.log("准备进入路由模板");
    next();
  },
  beforeRouteLeave: (to, from, next) => {
    console.log("准备离开路由模板");
    next();
  }
}

你可能感兴趣的:(vue)