最近做的Vue2项目中,都涉及到一种场景,那就是一个组件(下称子组件)被同一个页面(下称父组件)多次调用。
本来以为这个场景没啥,但是在实际做的过程,发现还是有必要注意一下的。需要注意的点在于:
子组件在其生命周期中是否进行了接口请求,如果进行了接口请求,那子组件被父组件调用了几次,那这个接口就会被请求了几次。如果子组件每次被调用时请求的是不同接口或同一个接口但参数不同,那也没问题, 但是如果子组件每次被调用时请求的接口相同、参数也相同,那么就属于接口重复请求了,会造成系统性能问题。
那么,对于这一问题,应该如何处理呢?
方案一:接口请求在父组件内进行,不在子组件的生命周期中请求接口
此方案可以有3种形式:
1.接口函数写在子组件内,但函数调用在父组件内进行。
js
this.$refs.child.getUnReadCount();
2.接口函数写在store中,父组件dispatch接口函数
js
this.$store.dispatch("riskUnread/getUnReadCount");
3.接口函数写在父组件内,父组件请求接口并把数据传给子组件
方案二: 接口请求仍在子组件的生命周期内进行,但进行特殊处理
特殊处理的思路如下:
- 有缓存拿缓存
- 没缓存判断如果是第 1 个请求的,就去请求接口
- 如果不是第 1 个请求的,就等
具体代码如下:
js
let cache = null;
let count = 0;
/**
* @param {Number} ms 延迟时间,单位毫秒
*/
async function delay(ms = 200) {
return new Promise((resolve) => setTimeout(resolve, ms));
};
export async function getData(params) {
try {
if (cache) {
return cache;
};
if (count++) {
// 如果有计数说明自己不是第 1 个,就等。
while (!cache) {
await delay();
};
} else {
// 是第 1 个就去请求
const res = await getListData(); //接口
cache = res;
};
count--; // 记得减回去,方便以后如果要刷新 cache 的时候用
return cache
} catch (error) {
};
};
番外
上面说的是一个组件被同一个页面多次调用可能会出现的问题,但别以为一个组件被不同的页面调用就没问题了。
本人在下面的场景中就遇到过问题:
有三个菜单页面都引用了一个列表组件,接口请求和数据处理都在该子组件内进行。其中,三个页面请求的接口是不同的,在子组件内根据入口判断请求哪个接口。
因需求要求每次打开菜单页面,都要刷新数据,所以,在子组件内,通过监听路由的方式,来刷新数据,代码如下:
js
// 子组件
watch: {
$route: function (newVal) {
if (newVal.path === '/crm/sale-manage/bid-list' ||
newVal.path === '/crm/workflow-manage/bid-allocate' ||
newVal.path === '/crm/workflow-manage/bid-accept') {
this.refresh(1)
}
},
},
然后,在这三个菜单中来回切换时,就会出现打开一个页面却最多请求3个不同接口的情况。
最后的解决方案是:把接口请求和路由监听都挪到父组件中。