当你在开玩笑测试中等待"anything"时,Vue 会计算 nextTick 吗?



我的示例组件显示了一个计数器(最初为"0"(和一个"0";增加";按钮它看起来像这样:

<div ref="label">{{ counter }}</div>
<div
ref="button"
@click="counter++"
>
Click me
</div>

如果我用Jest测试点击行为,下面的测试将无法通过

it('increases the counter when the button is clicked', async () => {
const button = testComponent.findComponent({ ref: 'button' })
button.vm.$emit('click');
const label = testComponent.findComponent({ ref: 'label' })
expect(label.text()).toBe('1'); // fails
});

正如我正确理解的那样,事件处理程序是同步调用的,但DOM更新仍在Vue的异步更新队列中等待。因此,为了使测试工作正常,我必须等待Vue.$nextTick()来更新DOM:

it('increases the counter when the button is clicked', async () => {
const button = testComponent.findComponent({ ref: 'button' })
button.vm.$emit('click');
await Vue.$nextTick();
const label = testComponent.findComponent({ ref: 'label' })
expect(label.text()).toBe('1'); // succeeds
});

但是我可以等待任何来更新DOM。我可以等待一个空物体,测试就会成功:

it('increases the counter when the button is clicked', async () => {
const button = testComponent.findComponent({ ref: 'button' })
button.vm.$emit('click');
await {};
const label = testComponent.findComponent({ ref: 'label' })
expect(label.text()).toBe('1'); // succeeds
});

我不明白为什么会这样。这是耶稣的一种特殊行为吗?为什么这样有效?

await null等待一段时间直到另一个在结算之前创建的承诺的通用方法,只有当另一个承诺立即结算时,它才能正常工作:

Promise.resolve().then(() => console.log('foo'));
await null;
console.log('bar'); // output is foo bar

文档建议将等待承诺的flush-promisessetTimeoutsetImmediate一起使用,这是一种等待更多的方式。

nextTick返回一个立即解析的promise,因此await Vue.nextTick()可以替换为await null。这在未来的Vue版本中不太可能改变,但如果改变了,这将破坏使用await null的代码。如果一个可以等待的承诺是可访问的,就像nextTick的情况一样,那么将其链接在语义上是正确的,至少这明确地指定了我们等待的内容。

最新更新