我是靠谱客的博主 无辜皮带,最近开发中收集的这篇文章主要介绍Vue 异步事件更新 & 异步Dom更新解决方案,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Vue 异步事更新件 & 异步Dom更新解决方案

    • Vue 异步事更新件 异步Dom更新解决方案
      • Question
      • Action
        • 1 正确姿势
        • 2 一个试验
        • 3 还有困惑

1. Question

这里写图片描述

最近遇到一个有点别扭的需求。

进入一个子页面,需要四个接口拿到四份数据【a,b,c,d】
其中a,b正巧父级拿到过,在父级页面上用v-if指令保证ab存在,再去展示子页面。

现在,cd必须在子页面拿到了。c依赖浏览器的query pidd依赖c的一个字段c.pgid

画一个图,大概是这样的需求:
这里写图片描述

然后我的旧实现思路是这样的:

// using typescript
private created() {
// 请求c后立刻请求d
this.fetchC().then(this.fetchD);
}
// 后台请求c
private fetchC() {
this.$store.dispatch('resource/c', this.pid);
}
// 从store获取c
private get c() {
return this.$store.getters['resource/c'](this.pid);
}
private get pid(): number {
return Number(this.$route.query.pid);
}
private get pgid() {
if (!this.c) {
return null;
}
return this.c.pgid;
}
// 后台请求d
private fetchD() {
if (!this.pgid) {
return;
}
return this.$store.dispatch('resource/d', this.pgid);
}
// store拿d
private get d() {
return this.$store.getters['resource/d'](this.pgid);
}

dispacth c之后立即then一下dispatch d。这个时候,get c()并不能保证一定已经get到,this.pgid更不一定能拿到,dispatch d方法就会报错。

这里写图片描述

当时有点蒙圈,其实很简单一个事,只要保证this.pgid存在的时候再去dispatch d就可以了。

2. Action

2.1 正确姿势

稍微改一点点代码:

// using typescript
private created() {
// 请求c后不去立刻请求d了
this.fetchC();
//
此行改了
}
// 后台请求c
private fetchC() {
this.$store.dispatch('resource/c', this.pid);
}
// 从store获取c
private get c() {
return this.$store.getters['resource/c'](this.pid);
}
private get pid(): number {
return Number(this.$route.query.pid);
}
private get pgid() {
if (!this.c) {
return null;
}
return this.c.pgid;
}
// 后台请求d,通过监听pgid的值,存在之后再去fetchD
@Watch('pgid')
// 此行改了
private fetchD() {
if (!this.pgid) {
return;
}
return this.$store.dispatch('resource/d', this.pgid);
}
// store拿d
private get d() {
if (!this.pgid) { return; }
// 此行改了
return this.$store.getters['resource/d'](this.pgid);
}

跑起来,一切都很完美。两个接口的数据都拿到了。

这是一个思路,把重心放在数据有没有拿到上,用watch监听,等数据拿到之后,再去发送第二个请求。

这里写图片描述

但是有点慌啊,这一块感觉还是有点迷啊。

我如果不把思路放在数据上,我就去控制请求(感觉这样子更符合开发的思路,代码更容易理解),有没有哪个生命周期的时刻,第一个请求回来,get的第一个数据也成功拿到,在这个生命周期时刻,第二个请求才开始呢?

第二个请求放在$nextTick里面行不行?
不论dispatch方法的快慢问题,到底getdispatch谁先执行?有没有一个先后顺序的?

这里写图片描述

2.2 一个试验

settimeout当作dispatch测试一下。

<html>
<head>
<title>test</title>
</head>
<body>
<div id="app">
<span>{{c}}</span>
<span>{{d}}</span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var app = new Vue({
el: '#app',
data: {
pgid : 1
},
computed: {
c: function () {
if (!this.pgid) {
return ;
}
console.log('c computed ' + this.pgid);
return ++this.pgid;
},
d: function () {
if (!this.c) {
return ;
}
console.log('d computed ' + this.c);
return ++this.c;
}
},
created: function () {
// 模拟c的请求,这里我不知道这个请求返回需要多少秒,假设1s
setTimeout(() => {
console.log('time out');
this.pgid = 100;
}, 1000);
this.$nextTick(() => {
console.log('next tick');
this.pgid = 10;
})
console.log('created');
},
mounted: function () {
console.log('mounted');
}
});
</script>
</body>
</html>

运行结果:

这里写图片描述

有图有真相了,看图学习:

官方对$nextTick的解释是:

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

官方对created方法的解释是:

在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。

官方对mounted方法的解释是:

el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。

注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted:

mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}

哦,也就是说在vue的created方法结束之后,mounted方法开始,紧接着执行$nextTick这个方法。

呸,我不信!
这里写图片描述

我把延迟改成0,我的请求巨快!

created: function () {
// 我把这个改成0
setTimeout(() => {
this.pgid = 100;
console.log('time out');
}, 0);
this.$nextTick(() => {
console.log('next tick');
this.pgid = 10;
})
console.log('created');
}

结果:

这里写图片描述

好吧,并没有什么变化,还是$nextTick快。

现在,起码明白了一个事: 遇到异步事件,你用拦截异步事件的思路是不通的,mountednextTick都拦不住,用settimeout延时你又不知道异步事件的延迟具体是多少秒。实际上异步事件执行的时间更靠后。而且远远晚于dom创建和首次展示的时间。

所以两个请求在created方法时就前后发出,第二个请求又依赖第一个请求的参数,这样的姿势肯定是不正确了。

2.3 还有困惑

get一定是在created方法之后?

并不是。。。。

这里写图片描述

getdispatch方法谁先执行???比如这个get dfetch d 都依赖pgidpgid一变,谁先变??也不一定。。。。

老老实实的用数据控制一切吧。

这里写图片描述

参考:
https://juejin.im/post/5a6fdb846fb9a01cc0268618

最后

以上就是无辜皮带为你收集整理的Vue 异步事件更新 & 异步Dom更新解决方案的全部内容,希望文章能够帮你解决Vue 异步事件更新 & 异步Dom更新解决方案所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(40)

评论列表共有 0 条评论

立即
投稿
返回
顶部