【1】路由入门
官网文档:https://router.vuejs.org/zh/installation.html
github: https://github.com/vuejs/vue-router
① 基础入门
① 下载安装
npm install vue-router --save
② 引入模块
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
③ 创建router 模块
index.js如下所示
/*
路由器对象模块
*/
import Vue from 'vue'
import VueRouter from 'vue-router'
import About from '../pages/About.vue'
import Home from '../pages/Home.vue'
// 声明使用vue-router插件
/*
内部定义并注册了2个组件标签(router-link/router-view),
给组件对象添加了2个属性:
1. $router: 路由器
2. $route: 当前路由
*/
Vue.use(VueRouter)
export default new VueRouter ({
// 注册应用中所有的路由
routes: [
{
path: '/about',
component: About
},
{
path: '/home',
component: Home,
},
{//根路由
path: '/',
redirect: '/about'
}
]
})
上面代码也可改写为如下方式:
/*路由器对象模块 */
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/about',
name: "About",
component: () =>import(/* webpackChunkName: "About" */ "../pages/About.vue")
},
{
path: '/home',
name:'Home',
component: () =>import(/* webpackChunkName: "Home" */ "../pages/Home.vue"),
},
{//根路由
path: '/',
redirect: '/about'
}
];
const router = new VueRouter({
mode: "history",
routes
});
export default router;
还可以指定绝对路径,如下所示:
//声明组件
import filmSchedule from '@/views/modules/filmSchedule/list'
//定义路由
{
path: '/filmSchedule',
name: '电影排片',
component: filmSchedule
},
④ 入口js-main.js中配置路由组件
/*
入口JS
*/
import Vue from 'vue'
import App from './App.vue'
import router from './router'
/*配置对象的属性名称都是确定的名称 ,不能随便修改 */
new Vue({
el: '#app',
components: {App}, // 映射组件标签
template: '<App/>', // 指定需要渲染到页面的模板
router // 注册路由器
})
⑤ 页面
<div class="list-group">
<!--生成路由链接-->
<router-link to="/about" class="list-group-item">About</router-link>
<router-link to="/home" class="list-group-item">Home</router-link>
</div>
<div class="panel-body">
<!--显示当前组件-->
<keep-alive>
<router-view msg="abc"></router-view>
</keep-alive>
</div>
② 重定向和别名
重定向也是通过 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
路由添加一个 beforeEnter
守卫并不会有任何效果。
别名
“重定向”的意思是,当用户访问 /a
时,URL 将会被替换成 /b
,然后匹配路由为 /b
,那么“别名”又是什么呢?
/a
的别名是 /b
,意味着,当用户访问 /b
时,URL 会保持为 /b
,但是路由匹配则为 /a
,就像用户访问 /a
一样。
上面对应的路由配置为:
const router = new VueRouter({
routes: [
{ path: '/a', component: A, alias: '/b' }
]
})
“别名”的功能让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构。
③ 命名路由
有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。你可以在创建 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.push()
是一回事:
router.push({ name: 'user', params: { userId: 123 } })
这两种方式都会把路由导航到 /user/123
路径。
【2】嵌套路由
路由模块的index.js
/*
路由器对象模块
*/
import Vue from 'vue'
import VueRouter from 'vue-router'
import About from '../pages/About.vue'
import Home from '../pages/Home.vue'
import News from '../pages/News.vue'
import Message from '../pages/Message.vue'
import MessageDetail from '../pages/MessageDetail.vue'
// 声明使用vue-router插件
Vue.use(VueRouter)
export default new VueRouter ({
// 注册应用中所有的路由
routes: [
{
path: '/about',
component: About
},
{
path: '/home',
component: Home,
children: [
{
path: '/home/news',//path最左侧/代表根路径
component: News
},
{
path: 'message',//这里没有用/ 表示相对路径
component: Message,
children: [
{
path:'detail/:id',
component: MessageDetail
}
]
},
{
path: '',
redirect: '/home/news'
}
]
},
{
path: '/',
redirect: '/about'
}
]
})
页面
<template>
<div>
<h2>Home</h2>
<div>
<ul class="nav nav-tabs">
<li><router-link to="/home/news">News</router-link></li>
<li><router-link to="/home/message">Message</router-link></li>
</ul>
<router-view></router-view>
</div>
</div>
</template>
【3】缓存路由组件对象
默认情况下, 被切换的路由组件对象会死亡释放, 再次回来时是重新创建的。如果可以缓存路由组件对象, 可以提高用户体验。
可以使用标签keep-alive
将router-view
包含,这样被访问过的路由就会保持生存。
<keep-alive>
<router-view></router-view>
</keep-alive>
【4】向路由组件传递数据
① 路由路径携带参数(param/query)
一个“路径参数”使用冒号 :
标记。当匹配到一个路由时,参数值会被设置到 this.$route.params
,可以在每个组件内使用。
配置路由
{
path: 'message',
component: Message,
children: [
{
path:'detail/:id',
component: MessageDetail
}
]
}
页面
<ul>
<li v-for="m in messages" :key="m.id">
//这里是ES6语法,ES5语法为''
<router-link :to="`/home/message/detail/${m.id}`">{{m.title}}</router-link>
</li>
</ul>
如上所示即可通过URL传递id到路由。路由组件中读取请求参数this.$route.params.id
。为什么不是this.$route.query.id
呢?是因为这里没有使用?id=XX
这种传参方式。
<script>
export default {
data() {
return {
detail: {}
}
},
// 改变当前路由组件参数数据时, 不会重新创建组件对象, mounted不会重新执行
mounted () {
const id = this.$route.params.id
this.detail = messageDetails.find(detail => detail.id===id*1)
},
watch: {
$route: function () { // 改变当前路由组件参数数据时自动调用
const id = this.$route.params.id
this.detail = messageDetails.find(detail => detail.id===id*1)
}
}
}
</script>
更多实例:
//两种正确写法
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
//当前页面
this.$router.push(`concertDetail?concertId=${id}`)
this.$router.push({ path: 'concertDetail', query: { "concertId": id } })
//concertDetail页面获取参数
this.$route.query.concertId
② <router-view>属性携带数据
页面如下所示:
<keep-alive>
<router-view msg="abc"></router-view>
</keep-alive>
在路由模板页面可取到msg:
<template>
<div>
<h2>About</h2>
<p>{{msg}}</p>
<input type="text">
</div>
</template>
<script>
export default {
props: {
msg: String
}
}
</script>
③ <router-link>
传递query参数
<router-link :to="{ path: '/front/activity/detail', query: { id: scope.row.activityId } }">
{{scope.row.activityName}}
</router-link>
更多详情参看官网:https://router.vuejs.org/zh/guide/essentials/navigation.html
【5】路由监听
背景:多个路由指向同一个页面,页面监听路由path,从来做出不同操作
//路由配置如下
{
path: 'knowledge1',
name: '性知识',
component: () => import('../views/admin/knowledge/list')
},
{
path: 'knowledge2',
name: '科学避孕',
component: () => import('../views/admin/knowledge/list')
},
{
path: 'knowledge3',
name: '婚前检查',
component: () => import('../views/admin/knowledge/list')
},
//监听配置如下
watch: {
'$route': {
handler(newRoute) {
console.log(newRoute)
const matches = newRoute.path.match(/\d+/g);
if (matches) {
//从path中解析出数字,发起对应请求
this.searchForm.type=matches.map(Number)[0]; // 将所有匹配结果转换为数字
this.getDataList()
}
},
immediate: true // 立即执行一次监听器
}
},