vue父组件传数据给子组件,子组件watch这个数据第一次有效,刷新页面就无效(同时解决请求数据时间过长,导致子组件过早渲染而无法获取到最新数据的问题)
需求&问题本文废话有点多,但我觉得有些业务场景应该也会有人遇到,索性还是把需求和问题都写详细点,看各位路过的朋友不说能解决你的问题,哪怕是对你有一点点帮助的,我也就很高兴了的????,嫌废话多的,直接看图应该就懂我的意思,我只留了关键的代码…问题1:本来是要向后台请求数据的,但是由于数据过大,后台需要处理,所以整个请求时间过长,可是我就是要拿到这个请求数据传给子组件,但实际上假如请求时间需
需求&问题
- 本文废话有点多,但我觉得有些业务场景应该也会有人遇到,索性还是把需求和问题都写详细点,看各位路过的朋友不说能解决你的问题,哪怕是对你有一点点帮助的,我也就很高兴了的😂,嫌废话多的,直接看图应该就懂我的意思,我只留了关键的代码…
问题1:本来是要向后台请求数据的,但是由于数据过大,后台需要处理,所以整个请求时间过长,可是我就是要拿到这个请求数据传给子组件,但实际上假如请求时间需要5s
,而子组件渲染完成只需要3s
,那就取不到数据了,我想到的解决办法有:
法1: 在子组件使用watch
去监听这个传来的props
,如代码:
父组件:
// 父组件的template
<template>
<assessChart :num="num"></assessChart>
</template>
// 父组件的methods
nextSycDetail({ qid: this.qid }).then((res) => {
if (res.data === null) {
return;
}
this.num = res.data; // 这个num就是要传给子组件的 props
})
子组件:
// 子组件的props
props:["num"]
// 子组件的watch
watch:{
num:{
deep:true,
handler(newVal){
// TODO
console.log("子组件接收到了参数...")
}
}
}
法2: 使用vuex,就是将这个num
属性放在vuex里面,然后夫组件请求数据成功后,把数据赋给vuex里的num
,再在子组件直接访问vuex里面的num
就行了。
总结
:
共同点
: 两者都是通过响应式的原理,去监听属性的变化,当请求结束之后,这个值就会变,一变也就是我拿到的请求后的数据了,然后再去做对应的操作
优缺点
: 推荐法1,因为法1是通过父子组件通信来传值的,传递的更加直接,也更加好理解;然而法2的话,你不仅要引入vuex来做中间者,虽然在实际项目中确实也很常用,引入到没什么,最麻烦的一点就是,你刷新页面的话,这个vuex它是会重新创建实例的,里面的数据又没了,也许作为开发者知道要避免刷新,那别人用户呢??他哪管你这些,他只知道页面有些东西没出来,就习惯性的去刷新一下,那你这样不就出问题了??除非你本地存储一份,刷新的时候更新一下vuex,不过这样岂不是又多了一个步骤??又增加了业务?
问题2:
上面的问题解决了,由于我的需求是有下一个的操作的,比如说我当前访问的数据A
的信息,当用户点击下一个应该访问的是数据B
的信息,可是用户在这个时候刷新页面,用户想看到的是数据B
的信息,而不是数据A
的信息,可刷新的话,我接口又是访问的数据A
的信息,这个没办法避免,因为这个接口的参数必须是从其他页面带过来的,所以我就做了一个本地存储的操作,也就是说当这个页面进来时,我会做一个判断,看用户是第一次进来页面还是后续刷新页面,第一次进来的话,我就正常请求接口,渲染页面,并本地存储一份; 如果是后续做了刷新操作,那我就从本地存储拿数据,这样子就可以保证不管你是一进就刷新,还是点了下一个再刷新,都是可以拿到用户想要的数据了。
可问题就是刷新页面的话,我父组件传给子组件num
确实也是最新的了,但就是子组件的watch
监听不到,因为数据没有变化,即使我在num
赋值前做了一个作弊的方法,就是随便给个值,比如
// 父组件的methods
nextSycDetail({ qid: this.qid }).then((res) => {
if (res.data === null) {
return;
}
localStorage.setItem("sycDetail", JSON.stringify(res.data)); // 本地存储一份
this.num = null; // 作弊方法也没用
this.num = res.data; // 这个num就是要传给子组件的 props
})
就是类似这样,想着强行让它数据变化,结果在子组件里面的watch
还是监听不到,不过在子组件里面created
或者mounted
生命周期里面去进行如下操作
// 子组件的created或者mounted,这里以created为例
created(){
this.num = JSON.parse(localStorage.getItem("sycDetail"));
}
但是这样是vue禁止的,不建议去直接修改父组件传来的props
的,控制台也会报错,虽然你可以在子组件里面的data里面去另外取一个变量,假如为:num_zi
,然后把传来的num
赋值给num_zi
,再在created
或者mounted
里面去进行
this.num_zi = JSON.parse(localStorage.getItem("sycDetail"));
,紧接着再去watch
这个num_zi
变量,看似可以,但是我试过也是不行,也许是我手法不对把,还请路过的大佬指教。。。。
最终解决办法:
在子组件中watch
这个传来的num
的时候加一个属性immediate
为true
,即:
子组件:
watch:{
num:{
deep: true,
immediate: true,
handler(newVal){
// TODO
console.log("子组件接收到了参数...")
}
}
}
说明:
(1)immediate
属性设置为true时,在watch中首次绑定的时候立即执行handle函数。
(2)immediate
属性设置为false时,和使用普通方式一样,只有在数据发生变化的时候才执行handler。
官方说明:
综上所诉:在子组件watch
监听父组件传的数据,并加上immediate
属性
更多推荐
所有评论(0)