今天做项目的时候,要实现 从商品详情页面,点击添加购物车后,跳转到购物车页面,同时将商品的信息展示在 购物车页面,即实现 路由跳转+传递数据
我能想到的一共有3种做法:
- 路由跳转+携带 query参数
- 路由跳转+ 全局事件总线 传递参数
- 路由跳转+ 本地会话存储
路由跳转+携带 query参数
路由跳转携带参数时,一般都是传递 基本数据类型【字符串, 数字等】
若是传递引用数据类型:vue路由传递一个对象作为参数的时候,不使用JSON.stringify和JSON.parse,接收参数的页面刷新后,接收的对象会变为[object Object]
//传递数据
this.$router.push({ name: "AddCartSuccess",
query: { skuInfo: JSON.stringify(this.skuInfo) },
params: {skuNum: this.skuNum} });
//接收数据
computed: {
skuNum() {
return this.$route.params.skuNum
},
skuName() {
let obj = JSON.parse(this.$route.query.skuInfo)
console.log(obj);
return obj.skuName
}
}
路由跳转+全局事件总线 传递参数
刚开始做的时候我想在路由跳转的时候,用$emit将需要的对象参数传递给购物车组件,但是 一直无法实现。最后调试半天后才发现,$eimt和$on的位置在此处有讲究。
组件路由跳转一般常用的两种方式:
- 声明式导航 router-link
- 编程式导航 this.$router.push({'/detail'})
在实现路由跳转的时候,VUE是默认销毁旧组件,创建新组件的。并且、$on 需要在$emit之前就准备好,这样才可以监听到数据。
结合组件的生命周期,我们发现 如果把this.$bus.$on 放在新组件的mounted中,那么新创建的组件中是无法展示旧组件传递过来的数据的。这是因为新组件的 mounted是在旧组件 beforeDestroy之后才发生的
p
s
ps
ps: 旧组件代指路由跳转前的组件 新组件代指路由跳转后的组件
正确示例:
//购物车路由跳转
async addShopcart() {
// skuId:this.$route.params.skuid, skuNum:this.skuNum
// 即调用仓库里面的 addOrUpdateShopCart 该方法返回的是一个promise对象 即成功/失败
try {
await this.$store.dispatch('addOrUpdateShopCart',
{ skuId: this.$route.params.skuid, skuNum: this.skuNum });
//商品加入购物车成功后
// 1. 先进行路由跳转
this.$router.push({ name: "AddCartSuccess" });
// 2. 将商品的信息进行传递
} catch (error) {
alert(error.message)
}
},
},
//此时注意 全局事件总线传递数据 不能写在路由跳转后,应该写在 beforeDestroy
beforeDestroy() {
this.$bus.$emit('sendItem', this.skuInfo)
},
}
上图反应了组件路由跳转时各个阶段的先后顺序,$on 一定要放在 $eimt之前
$on: 监听当前实例上的自定义事件
$emit: 触发当前实例上的事件 要传递的数据会传给监听器
$on 一定要先执行 在执行$emit 触发事件
总结一波
1. 任何组件都可以在事件总线中发布事件 this.$bus.$emit('xxx','传递参数')
2. 任何组件都可以在事件总线中监听事件 this.$bus.$on('xxx',(接收参数)=>{ 对形参进行操作 })
3. main.js注册空的Vue对象, 只负责$on注册事件, $emit触发事件, 一定要确保$on先执行
4. $off的格式:
$off() 会取消所有的事件订阅;
$off('事件名') 会取消指定事件名的;
$off('事件名', 回调) 会取消指定事件名的,指定回调
路由跳转+本地会话存储
this.$router.push({ name: "AddCartSuccess", params: { skuNum: this.skuNum } });
// 浏览器本地存储功能 在路由跳转之前 存储在浏览器中
sessionStorage.setItem('SKUINFO', JSON.stringify(this.skuInfo))
computed: {
skuNum() {
return this.$route.params.skuNum
},
skuInfo() {
let skuInfo = JSON.parse(sessionStorage.getItem('SKUINFO')) || {}
return skuInfo
},
}