vue路由基本使用
首先,路由是什么。路由,其实就是指向的意思,当我点击页面上的home按钮时,页面中就要显示home的内容,如果点击页面上的about 按钮,页面中就要显示about 的内容。Home按钮 => home 内容, about按钮 => about 内容,也可以说是一种映射. 所以在页面上有两个部分,一个是点击部分,一个是点击之后,显示内容的部分。
路由中有三个基本的概念 route, routes, router。
-
route,它是一条路由,由这个英文单词也可以看出来,它是单数, Home按钮 => home内容, 这是一条route, about按钮 => about 内容, 这是另一条路由。
-
routes 是一组路由,把上面的每一条路由组合起来,形成一个数组。[{home 按钮 =>home内容 }, { about按钮 => about 内容}]
-
router 是一个机制,相当于一个管理者,它来管理路由。因为routes 只是定义了一组路由,它放在哪里是静止的,当真正来了请求,怎么办? 就是当用户点击home 按钮的时候,怎么办?这时router 就起作用了,它到routes 中去查找,去找到对应的 home 内容,所以页面中就显示了 home 内容。
-
客户端中的路由,实际上就是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。
项目实际操作及讲解
- 在 components 中创建两个页面,one.vue 和 two.vue
<template>
<div class='one'> //two页面也同样如此
one
</div>
</template>
- 在 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')
}
]
- 把路由注入到根实例中,启动路由。这里其实还有一种方法,就像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)
})
- 页面中写按钮,第一种方法是用事件来触发路由进行跳转,第二种方法是用
<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' }})
上述需要注意的是,如果提供了 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
同样的规则也适用于 router-link 组件的 to 属性。
- 这时候页面上的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-link中to 属性中的动态部分。使用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 页面下还有很多分类,例如 Home1 和 Home2,在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,而不是受限于配置的嵌套路由结构。