我在写仿大众点评的时候遇到一个问题:虽然进入不同商品详情页,router的path也变了,但是页面的数据没有发生改变。然后我看了Vue.js的官网,看到了这样一段话:
提醒一下,当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
然后我知道了可以通过使用watch 去监测 $route 对象和Vue Router 2.2 中引入的 beforeRouteUpdate 导航守卫两种方法去监测并获取数据。以下是两种方法的写法
watch (监测变化) $route 对象
1、在data属性定义数据
data() {
return {
dianpu: [],
dianpuIndex: 0
};
},
2、在mounted()钩子函数中写vm.$nextTick
mounted() {
this.$nextTick(() => {
this.dianpuIndex = this.$route.params.index;
this.dianpu = this.$store.state.dianpu[this.dianpuIndex];
});
}
3、写watch监听方法
必须写if条件,否则退出页面的时候会报错
watch: {
$route(to, from) {
if (to.path != "/home") {
this.dianpuIndex = this.$route.params.index;
this.dianpu = this.$store.state.dianpu[this.dianpuIndex];
}
}
},
导航守卫
什么是动态路由
在我写的vue项目中,猜你喜欢的商品很多,对所有商品详情页面都需要使用guessLikeDetails这个组件来渲染,所以需要使用动态路由。
export default new Router({
// mode: 'hash',
routes: [
{
// 动态路径参数 以冒号开头
path: '/guessLikeDetails/:index',
component: guessLikeDetails,
},
],
linkActiveClass: 'active'
})
导航守卫分全局的, 单个路由独享的, 或者组件级的。这里我们简单介绍一下路由独享的守卫
beforeEnter
可以在路由配置上直接定义 beforeEnter 守卫
{
path: '/guessLikeDetails/:index',
component: guessLikeDetails,
beforeEnter: (to, from, next) => {
console.log("to", to);
console.log("from", from);
console.log("next", next);
}
}
组件内的守卫
在这个项目中我是使用组件内的守卫beforeRouteEnter来监听数据的变化,以下是使用beforeRouteEnter的步骤:
1、同样是定义data的数据
data() {
return {
dianpu: [],
dianpuIndex: 0
};
},
2、在vue组件里面写beforeRouteEnter
beforeRouteEnter不能获取组件实例 this,因为守卫在导航确认前被调用,因此新组件还没被创建。所以需要在next方法里传vm,vm就代表了组件实例。beforeRouteEnter在/guessLikeDetails/1直接跳转到/guessLikeDetails/2时不起作用,需要你从/guessLikeDetails/1退回到/home再进入/guessLikeDetails/2时才会监听数据的变化。
beforeRouteEnter(to, from, next) {
next(vm => {
vm.dianpuIndex = to.params.index;
vm.dianpu = vm.$store.state.dianpu[vm.dianpuIndex];
});
},
beforeRouteUpdate
beforeRouteUpdate能访问this,但是我打印出来的this不是vue实例。beforeRouteUpdate在/guessLikeDetails/1直接跳转到/guessLikeDetails/2时起作用。
beforeRouteUpdate: (to, from, next) => {
console.log(this, "beforeRouteUpdate");
console.log(this)
next();
},
beforeRouteLeave
这个this是vue实例,只在退出/guessLikeDetails/:index页面的时候才起作用,在页面/guessLikeDetails/1直接跳转到/guessLikeDetails/2时不起作用
beforeRouteLeave(to, from, next) {
console.log(this);
next();
},
为什么beforeRouteUpdate不起作用(即使路径发生变化)
有两个原因:
1、使用导航守卫必须去掉history模式
2、使用导航守卫必须在动态路径的vue组件中使用!!!
举个例子:虽然我写的路径切换在Guess-you-like-it.vue组件中,(guessLikeDetails组件import了Guess-you-like-it组件),但是你写导航守卫必须在guessLikeDetails组件中!!!!
ps:如果想要完整代码,欢迎下载我的github项目:仿大众点评
https://github.com/faimi/Fan_DAZHONGDIANPING.git