事件处理
Vue 组件通过 props 和通过调用 $emit
发射事件来相互交互。在本指南中,我们将了解如何使用 emitted()
函数验证事件是否正确发射。
本文也以 简短视频 的形式提供。
计数器组件
这是一个简单的 <Counter>
组件。它包含一个按钮,当点击该按钮时,会递增内部计数变量并发射其值
const Counter = {
template: '<button @click="handleClick">Increment</button>',
data() {
return {
count: 0
}
},
methods: {
handleClick() {
this.count += 1
this.$emit('increment', this.count)
}
}
}
为了完全测试此组件,我们应该验证是否发射了带有最新 count
值的 increment
事件。
断言发射的事件
为此,我们将依赖 emitted()
方法。它 **返回一个包含组件发射的所有事件的对象**,以及它们的参数(以数组形式)。让我们看看它是如何工作的
test('emits an event when clicked', () => {
const wrapper = mount(Counter)
wrapper.find('button').trigger('click')
wrapper.find('button').trigger('click')
expect(wrapper.emitted()).toHaveProperty('increment')
})
如果您以前没有见过
trigger()
,不用担心。它用于模拟用户交互。您可以在 表单 中了解更多信息。
首先要注意的是 emitted()
返回一个对象,其中每个键都与一个发射的事件匹配。在本例中,是 increment
。
此测试应该通过。我们确保发射了具有适当名称的事件。
断言事件的参数
这很好 - 但我们可以做得更好!我们需要检查当调用 this.$emit('increment', this.count)
时,我们是否发射了正确的参数。
我们的下一步是断言该事件包含 count
值。我们通过将参数传递给 emitted()
来做到这一点。
test('emits an event with count when clicked', () => {
const wrapper = mount(Counter)
wrapper.find('button').trigger('click')
wrapper.find('button').trigger('click')
// `emitted()` accepts an argument. It returns an array with all the
// occurrences of `this.$emit('increment')`.
const incrementEvent = wrapper.emitted('increment')
// We have "clicked" twice, so the array of `increment` should
// have two values.
expect(incrementEvent).toHaveLength(2)
// Assert the result of the first click.
// Notice that the value is an array.
expect(incrementEvent[0]).toEqual([1])
// Then, the result of the second one.
expect(incrementEvent[1]).toEqual([2])
})
让我们回顾一下并分解 emitted()
的输出。这些键中的每一个都包含在测试期间发射的不同值
// console.log(wrapper.emitted('increment'))
;[
[1], // first time it is called, `count` is 1
[2] // second time it is called, `count` is 2
]
断言复杂事件
想象一下,现在我们的 <Counter>
组件需要发射一个包含附加信息的 Object。例如,我们需要告诉任何监听 @increment
事件的父组件 count
是偶数还是奇数
const Counter = {
template: `<button @click="handleClick">Increment</button>`,
data() {
return {
count: 0
}
},
methods: {
handleClick() {
this.count += 1
this.$emit('increment', {
count: this.count,
isEven: this.count % 2 === 0
})
}
}
}
与之前一样,我们需要触发 <button>
元素上的 click
事件。然后,我们使用 emitted('increment')
来确保发射了正确的 value。
test('emits an event with count when clicked', () => {
const wrapper = mount(Counter)
wrapper.find('button').trigger('click')
wrapper.find('button').trigger('click')
// We have "clicked" twice, so the array of `increment` should
// have two values.
expect(wrapper.emitted('increment')).toHaveLength(2)
// Then, we can make sure each element of `wrapper.emitted('increment')`
// contains an array with the expected object.
expect(wrapper.emitted('increment')[0]).toEqual([
{
count: 1,
isEven: false
}
])
expect(wrapper.emitted('increment')[1]).toEqual([
{
count: 2,
isEven: true
}
])
})
测试 Object 等复杂事件有效负载与测试数字或字符串等简单值没有什么不同。
组合 API
如果您使用的是组合 API,您将调用 context.emit()
而不是 this.$emit()
。emitted()
会捕获来自两者的事件,因此您可以使用此处描述的相同技术来测试您的组件。
结论
- 使用
emitted()
访问从 Vue 组件发射的事件。 emitted(eventName)
返回一个数组,其中每个元素代表一个发射的事件。- 参数存储在
emitted(eventName)[index]
中,以数组形式存储,顺序与它们发射的顺序相同。