$router
和$route
的区别:$router
:就那个全局唯一的VueRouter
对象,挂载在Vue
对象里,包括我们定义的路由规则,有钩子函数、push,replace,go,back,forward,addRoutes
等方法,所以每个组件里this.$router
拿到的都是同一个实例;$route
:路由信息对象,就是我们配置路由规则数组里的对象的再次封装,常用属性:fullPath、path,meta、hash,matched,name、query,params
,后2个属性是取传递过来的参数的(参数传递方法不同,取参数用到的属性就不同),vue会把当前活跃的route对象赋值给Vue.prototype.$router
上,所以可以说每个组件的this.$route
对象是不同的;
- router-link和router-view,从vue-router的源码看,是因为注册为Vue的全局组件
Vue.component('RouterLink',Link)
和Vue.component('RouterView',View)
- 2种路由传参数方式
- params方式取参数,在url里拼接
// 1.路由规则设置时,path要用占位符:
const router = new VueRouter({
routes: [
{ path: "/home/:name/state/:id", component: Home },
{ path: "/about", component: About },
],
});
// 2. html的链接写法,拼接参数,生成a标签后,url地址:/home/张三
<router-link :to="'/home/'+obj.name+'/state/'+obj.id">home</router-link> // 字符串与变量拼接
// 3.在其他组件里获取参数的方法
$route.params // { "name": "张三", "id": "11" }
- query方式取参数,可以传对象,对象序列化在url里的?后面(键值对&符号拼接),数据量大用此方式,
// 1.这次html改用button按钮标签,当然也可以用router-link标签,只是在html里加入很多js代码,不合适
<button @click="clickAbout">关于</button>
//<router-link
// :to="{
// path:'/about',
// query:{
// id: 10,
// name: '李四',
// gender: 'male',
//}}"
// >关于1</router-link>
// 2.在点击函数里传参数,query就是个对象,而且键值对会附加在url的?后面:/about?id=11&name=张三&gender=male
methods: {
clickAbout() {
this.$router.push({
path: "/about",
query: {
id: 11,
name: "张三",
gender: "male",
},
});
},
},
// 3.取值
$route.query // { "id": "11", "name": "张三", "gender": "male" }
- 路由可选参数,路由参数改为可选方法:
path: '/edit/:id?',
,id可以不传也可以不传; beforeEach()
,全局前置守卫,比组件的生命周期函数执行更早
// 设置页面标题,前提是设置路由规则时,每条规则除了必要的path和component属性外,要加上meta这个对象
router.beforeEach((to,from,next) => {
document.title = to.matched[0].meta.title
next()
})
// 页面跳转前判断是否有登录,通过判断Token
router.beforeEach((to, from, next) => {
NProgress.start()
if (to.path === '/login') return next()
const token = window.localStorage.getItem('token')
if (token) return next()
next('/login')
})
afterEach()
,全局后置钩子,跳转后回调,比组件的生命周期函数执行更早,先执行beforeEach,再执行afterEach,最后事组件的生命周期,beforeCreate,Created等等;
router.afterEach((to, from) => {
console.log("afterEach");
});
6. 路由独享的守卫
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
- 组件内的守卫
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
- 路由懒加载
// 这种不是懒加载,所以最终会被打包到一个综合的js文件里,导致js文件体积大
// import Home from '../views/Home.vue'
const routes = [
//home.vue会被单独生成一个js文件,但js文件名称事随机的
{
path: '/home',
name: 'Home',
component: () => import('../views/Home.vue')
},
//home.vue会被单独生成一个js文件,但名称里有home字样,比如Home.60b68e47.js
{
path: '/home',
name: 'Home',
component: () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')
},
]