vue 路由基础

1,303 阅读5分钟

vue路由基本使用

首先,路由是什么。路由,其实就是指向的意思,当我点击页面上的home按钮时,页面中就要显示home的内容,如果点击页面上的about 按钮,页面中就要显示about 的内容。Home按钮  => home 内容, about按钮 => about 内容,也可以说是一种映射. 所以在页面上有两个部分,一个是点击部分,一个是点击之后,显示内容的部分。

路由中有三个基本的概念 route, routes, router。

  1. route,它是一条路由,由这个英文单词也可以看出来,它是单数, Home按钮  => home内容, 这是一条route,  about按钮 => about 内容, 这是另一条路由。

  2. routes 是一组路由,把上面的每一条路由组合起来,形成一个数组。[{home 按钮 =>home内容 }, { about按钮 => about 内容}]

  3. router 是一个机制,相当于一个管理者,它来管理路由。因为routes 只是定义了一组路由,它放在哪里是静止的,当真正来了请求,怎么办? 就是当用户点击home 按钮的时候,怎么办?这时router 就起作用了,它到routes 中去查找,去找到对应的 home 内容,所以页面中就显示了 home 内容。

  4. 客户端中的路由,实际上就是dom 元素的显示和隐藏。当页面中显示home 内容的时候,about 中的内容全部隐藏,反之也是一样。客户端路由有两种实现方式:基于hash 和基于html5 history api此段为搬运

在js中配置路由

首先要定义route,  一条路由的实现。它是一个对象,由两个部分组成: path和component.  path 指路径,component 指的是组件。如:{path:’/home’, component: Home}

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/', name: 'Home', component: Home
  },
  {
    path: '/about',name: 'About',component: () => import('../views/About.vue')
  }
]

//创建router 对路由进行管理,它是由构造函数 new vueRouter() 创建,接受参数。
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes   // routes: routes 的简写
})

export default router
//配置完成后,main.js中把router 实例注入到 vue 根实例中,就可以使用路由了
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

上述这些在配置模板的时候一般会默认携带,执行过程是:当用户点击 router-link 标签时,会去寻找它的 to 属性, 它的 to 属性和 js 中配置的路径{ path: '/home', component: Home}  path 一一对应,从而找到了匹配的组件, 最后把组件渲染到 <router-view> 标签所在的地方。所有的这些实现才是基于hash 实现的。

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

我们可以借助 router 的实例方法,通过编写代码来实现路由跳转,也就是官方说的编程式导航详情请去往Router官网查看

注意:在 Vue 实例内部,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push

项目实际操作及讲解

  1. 在 components 中创建两个页面,one.vue 和 two.vue
 <template>
   <div class='one'>    //two页面也同样如此
        one
   </div>
</template>
  1. 在 src目录下的 router.js 中定义 router, 就是定义 路径到 组件的 映射。也就是注册路由

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/one',
    name: 'one',
    component: () => import('../components/one.vue')
  },
  {
    path: '/two',
    name: 'two',
    component: () => import('../components/two.vue')
  }
]
  1. 把路由注入到根实例中,启动路由。这里其实还有一种方法,就像vuex  store 注入到根实例中一样,我们也可以把vueRouter 直接注入到根实例中。在main.js中引入路由,注入到根实例中。
import Vue from 'vue'
import App from './App.vue'
 
// 引入路由
import router from "./router.js"    // import router 的router 一定要小写, 不要写成Router, 否则报 can't match的报错

new Vue({
  el: '#app',
  router,  // 注入到根实例中
  render: h => h(App)
})
  1. 页面中写按钮,第一种方法是用事件来触发路由进行跳转,第二种方法是用<router-link>来进行跳转
<template>
   <div class='one'>
        one
        <button @click="goTwo">去two组件</button>
        
        ```
     <!-- 使用 router-link 组件来导航. -->
     <!-- 通过传入 `to` 属性指定链接. -->
     <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
    <router-link to="/two">Go to Two</router-link>
    
   </div>
</template>
<script>
export default {
   methods:{
    goTwo(){
        this.$router.push("/two")   //这里用了path进行跳转
    }
  }
}
</script>

当你点击 <router-link> 时,这个方法会在内部调用,所以说,点击 <router-link :to="..."> 等同于调用 router.push(...)

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

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

// 字符串
router.push('home')

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

// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

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

上述需要注意的是,如果提供了 pathparams 会被忽略,上述例子中的 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

同样的规则也适用于 router-link 组件的 to 属性。

  1. 这时候页面上的one已经可以进行跳转,但是首次进入页面的时候,路由的默认路径是 “/”,所以我们需要让 “/” 指向 one ,但是我们不能直接写{ path: '/', component: Home },因为两条路径指向同一个方向,vue会报错,所以这时候我们就会用到 重定向,也就是让他改变指向,指向另一个方向,vueRouter中用 redirect 来定义重定向。
const routes = [
  {
    path: '/',
    redirect:'/one',   //重定向,将 ‘/’ 指向 one
    name: 'one',
    component:() => import('../components/one.vue')
  },
  {
    path: '/one',
    name: 'one',
    component: () => import('../components/one.vue')
  },
  {
    path: '/two',
    name: 'two',
    component: () => import('../components/two.vue')
  }
]

这时候基本的路由跳转也就完成了。

路由理解

动态路由

我们经常需要吧某种模式匹配到的所有路由,全都映射到同个组件。例如就是在一个User的组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果:

const User = {
  template: '<div>User</div>'
}

const router = new VueRouter({
  routes: [
    // 动态路径参数 以冒号开头
    { path: '/user/:id', component: User }
  ]
})

一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。于是,我们可以更新 User 的模板,输出当前用户的 ID:

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}

当整个vue-router 注入到根实例后,在组件的内部,可以通过 this.$route 来获取到 router 实例。params 属性用来获得这个动态部分。它是一个对象,属性名,就是路径中定义的动态部分 id, 属性值就是router-linkto 属性中的动态部分。使用vuex时,组件中想要获取到state 中的状态,是用computed 属性,在这里也是一样,在组件中,定义一个computed 属性dynamicSegment,  user 组件修改如下:

<template>
    <div>
        <h1>User</h1>
        <div>我是user组件, 动态部分是{{dynamicSegment}}</div>
    </div>
</template>
<script>
    export default {
        computed: {
            dynamicSegment () {
                return this.$route.params.id
            }
        }
    }
</script>

还有一个问题就是我们在来回切换动态路由的时候,这时如果想要在组件来回切换的时候做点事情,由于是同一个组件,vue不会再销毁重新创建,而是复用,实现组件的生命周期不管用了,我们需要在组件内部(user.vue中)利用 watch 来监听$route 的变化。把上面的代码用监听$route

<script>
    export default {
        data () {
            return {
                dynamicSegment: ''
            }
        },
        watch: {
            $route (to,from){
                // to表示的是你要去的那个组件,from 表示的是你从哪个组件过来的,它们是两个对象,你可以把它打印出来,它们也有一个param 属性
                console.log(to);
                console.log(from);
                this.dynamicSegment = to.params.id
            }
        }
    }
</script>

嵌套路由

嵌套路由,例如就是在主页 Home 页面下还有很多分类,例如 Home1Home2,在vue中,是先加载Home组件再进入 Home 的子元素,所以vue 提供了childrens 属性,它也是一组路由,相当于我们所写的routes

    <!-- router-link 的to属性要注意,路由是先进入到home,然后才进入相应的子路由如 phone,所以书写时要把 home 带上 -->
    <router-link to="/home/home1"> home1 </router-link>

在route.js 中 需要加 children 属性

const routes = [
    {
        path:"/home",
     // component属性也不能少,因为,我们是先进入home页面,才能进入子路由
        component: home,
     // 子路由
        children: [
            {
                path: "/home1",
                component: home1
            },
            {
                path: "/home2",
                component: home2
            }
        ]
    },
    {
        path: "/about",
        component: about
    },
    {
        path: "/user/:id",
        component: user
    },
    {
        path: '/', 
        redirect: '/home' 
    }
]

当然跟我们首页面进入的时候一样,当进入home时,此时路由的路径是 /home/, 所以我们应该给他一个默认指向,

// 当进入到home时,下面的组件显示
{
  path: "",
  component: phone
}

命名路由

也就是路由的一个名字,可以给定义一个名字,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。

你可以在创建 Router 实例的时候,在 routes 配置中给某个路由设置名称。

const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'user',
      component: User
    }
  ]
})

要链接到一个命名路由,可以给 router-link 的 to 属性传一个对象:

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

同时  router-link 也是这么回事

router.push({ name: 'user', params: { userId: 123 } })

这两种方式都会把路由导航到 /user/123 路径。

详解重定向

重定向

重定向,也是通过 routes 配置来完成,下面例子是从 /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 重定向的 字符串路径/路径对象
    }}
  ]
})

别名

重定向”的意思是,当用户访问 /a时,URL 将会被替换成 /b,然后匹配路由为 /b,“别名”的意思是,/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样。一个是被替换,一个是被叫做

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

别名的功能让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构。

vue Router官网