基础
1 起步
命名路由:通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。
你可以在创建 Router 实例的时候,在 routes 配置中给某个路由设置名称。
配置路由 注意name,添加name属性则为命名路由。
// router/index.js
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
const routes = [
{
path: "/",
name: "Home",
component: Home
},
{
path: "/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")
},
{
path: '*',
redirect: '/' // 默认加载路由, 输入地址没有匹配上,则会匹配地址为 / 的路由
},
// { // 会匹配所有路径
// path: '*',
// component: () => import('../views/404.vue') // 通配符 适合做404页面路由
// }
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
// main.js
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
Vue.config.productionTip = false;
//挂载路由
new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
// app.vue
<router-link to="/">go to home</router-lnk>
<router-link to="/about">go to about</router-link>动态
<router-view></router-view>
2 动态路由配置
我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 User 组件,对 于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中 使用“动态路径参数”(dynamic segment) 来达到这个效果:
//1 配置动态路由
{
path: '/test/:name', // 动态路径参数 以冒号开头
component: () =>import( "../views/test.vue")
}
//2 页面 两种方式 动态绑定 router-link 将当前的dom元素变成超链接
<router-link :to="`/test/${name}`">
{{name}}go to test.vue
</router-link>
<router-link :to="'/test/'+name">
{{name}}go to test.vue
</router-link>
//3 获取路由的值
this.$route.params获取动态路由的值
3 嵌套路由
实际生活中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构 对应嵌套的各层组件
//路由配置
{
path: "/about",
name: "About",
component: () => import("../views/About.vue"),
children:[
{
path:':name',
name:'detail',
component:() => import("../views/Detail.vue"),
}
]
},
//父路由配置
<router-link :to="`/about/${name}`">
{{name}} go to detail.vue
</router-link>
<router-view></router-view> // 嵌套内容出口
//3 获取路由的值
this.$route.params获取动态路由的值
4 命名路由
通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。 你可以在创建 Router 实例的时候,在 routes 配置中给某个路由设置名称。
{
path: '/mobile/:name',
name:"mobile",
component: () =>
import("../views/contact/mobile.vue")
},
// 要链接到一个命名路由,可以给 router-link 的 to 属性传一个对象:
<router-link :to="{name:'mobile',params:{name:'张三',mobile:'139'}}"></router-link>
//调用router.push()
router.push({ name: 'mobile',params:{name:'张三',mobile:'139'}})
5 编程导航
//路由跳转 跳转location地址 onComplete 路由跳转完成后调用, onAbort取消跳转后调用
this.$router.push(location,onComplete?,onAbort?);
// 字符串
this.$router.push('home')
// 对象 path:地址
this.$router.push({ path: 'home' })
// 命名的路由 name router名称=>path的值
this.$router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
this.$router.push({ path: 'register', query: { plan: 'private' }})
//示例
methods: {
onClick() {
this.$router.push({ path: 'register', query: { plan: 'private' }})
}
},
//组件复用时注意事项:
//响应路由参数变化
watch: {
$route: { // 用户自定义watcher
immediate: true,
deep: true,
handler() {
console.log("路由变化之后 执行动作");
}
}
},
进阶
路由守卫
1 全局守卫
//全局路由守卫
router.beforeEach((to,from,next)=>{
//to: Route即将要进入的目标 路由对象
// from: Route当前导航正要离开的路由
// next:Function 一定要调用该方法来resolve这个钩子
});
// 范例: 守卫 About.vue
1、配置路由
{
path: "/about",
name: "About",
component: () => import("../views/About.vue"),
children:[
{
path:':name',
name:'detail',
component:() => import("../views/Detail.vue"),
}
],
meta:{
auth:true
}
},
{
path:'/login',
component:()=>import('../views/Login.vue'),
},
2 配置全局守卫
router.beforeEach((to,from,next)=>{
if(to.meta.auth){
if(window.isLogin){
next();
}else{
next('/login?redirect='+to.fullPath); // redirect查询参, 回到跳转时的路由
}
}else{
next();
}
});
3 访问
this.$router.push(this.$route.query.redirect);
2 独享守卫
{
path: "/about",
name: "About",
component: () => import("../views/About.vue"),
children:[
{
path:':name',
name:'detail',
component:() => import("../views/Detail.vue"),
}
],
meta:{
auth:true
},
beforeEnter(to,from,next){
if(window.isLogin){
next();
}else{
next('/login?redirect='+to.fullPath);
}
},
},
3 组件内守卫
可以在组件内直接定义以下路由导航守卫
beforeRouteEnter // 进入目标路由之前触发
beforeRouteUpdate // 当前路由参数发生变化 比如动态路由
beforeRouteLeave //离开当前路由触发
// About.vue
<script>
export default {
data() {
return {
name: "李四",
}
},
beforeRouteEnter(to,from,next){
if(window.isLogin){
next();
}else{
next('/login?redirect='+to.fullPath);
}
},
}
</script>
4 数据获取
1 路由导航前
// 组件未渲染,通过给next传递回调访问组件实例
beforeRouteEnter (to, from, next) {
getPost(to.params.id, post => {
next(vm => vm.setData(post))
}) },
// 组件已渲染,可以访问this直接赋值
beforeRouteUpdate (to, from, next) {
this.post = null
getPost(to.params.id, post => {
this.setData(post) next()
})
},
2 路由导航后
created () {
this.fetchData()
},
watch: {
'$route': 'fetchData'
}
动态路由
根据用户角色通过router.addRoutes(routes)方式动态添加路由
// 全局守卫修改为 : 要求用户必须登录,否则只能去登录页面
router.beforeEach((to,from,next)=>{ // 全局守卫
if(window.isLogin){//已经登录
if(to.path === '/login'){
next('/');
}else{
next();
}
}else{// 没有登录
if(to.path === '/login'){
next();
}else{
next('/login?redirect=' + to.fullPath);
}
next();
}
});
// login.vue 用户登录成功后动态添加路由 /about
login(){
window.isLogin=true;
this.$router.addRoutes([
{
path:'/about',
// ......
}
]);
this.$router.push(this.$route.query.redirect || '/'); // 跳转路由
}
路由缓存
注意: 使用include 或exclude时 要给组件设置name
//利用keepalive做组件缓存,保留组件状态,提高执行效率
// 范例 缓存 about组件
// about 的值为 组件的名称 , 多个名称用 ',' 隔开
// 仅缓存about组件 max表示最多缓存的组件数量,超过后先进先出
<keep-alive include='about' max='10'>
<router-view />
</keep-alive>
// 除了about组件外,其他组件都缓存
<keep-alive exclude='about'>
<router-view />
</keep-alive>
// aboute组件
export default {
name:'about',
data() {
return {
name: "李四",
school:[],
}
},
}
// 两个特别的生命周期钩子
// 当设置 缓存about时, 进入about时会触发activated钩子,离开aboute会触发deactivated
export default {
name:'about',
data() {
return {
name: "李四",
school:[],
}
},
activated(){
console.log('activated');
},
deactivated(){
console.log('deactivated');
},
}
路由懒加载
路由组件的懒加载能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
() => import("../views/About.vue")
//把组件按组分块
() => import(/* webpackChunkName: "group-about" */ "../views/About.vue")