让我们以下面的场景为例,其中WelcomePage (父)使用LoginForm (子)与自定义事件@submit
// WelcomePage.vue
<LoginForm @submit="handleLogin">Login<Button>然后,组件LoginForm具有以下代码:
// LoginForm
<form @submit.prevent="handleSubmit"> ... </form>handleSubmit() {
// do some stuff...
// following Vue docs to create custom events.
this.$emit('submit', 'some_data')
// OR... we can also use $listeners.
this.$listeners.submit('some_data')
// do other stuf...
}用this.$listeners.submit()代替this.$emit('submit')有什么坏处吗?
使用this.$listeners的一个优点是它可以与await一起使用,是$emit的一个限制迫使我们使用done()回调方法。当我们想在定制事件完成后更新某个状态(this.isLoading)时,它是非常有用的。
使用带有回调的$emit:
// LoginForm.vue
async handleSubmit() {
this.isLoading = true
this.$emit('submit', 'some_data', () => {
this.isLoading = false
})
}
// WelcomePage.vue
async handleLogin(data, done) {
// await for stuff related to "data"...
done();
}使用$listeners和await:
// LoginForm.vue
async handleSubmit() {
this.isLoading = true
await this.$listeners.submit('some_data') // no need to use done callback
this.isLoading = false
}所以,我的问题是:使用this.$listeners可以吗?this.$emit的目的/优点是什么?
更新:
第一个(明显的)选项是将一个道具isLoading从父级传递给子级,而不是使用$emit。
但是,这需要在每次使用子组件时在handleSubmit上设置和更新handleSubmit(它经常使用)。因此,我正在寻找一种解决方案,在调用isLoading时,父级不需要担心@submit。
发布于 2020-03-05 22:58:07
在我看来,$emit帮助您保持流量体系结构。您可以很容易地看到数据流,它帮助您调试。
另一方面,使用$listeners被认为是一种不好的做法。这是可以做到的,但它可以破坏单向数据流。同样,对于$root,您仍然可以访问它,但这并不意味着您应该使用(修改)它;-)
然而,使用什么始终取决于上下文和您的需要。只是要小心,一旦破坏了单向数据流,就很难调试。
评论后的编辑:这只是我对它的看法。
当使用props和$emit作为组件间通信的推荐方式时。你有一个清晰的数据流。此外,Vue开发工具还可以帮助您跟踪每个$emit,因此您可以一步一步准确地知道发生了什么。
当使用"collbackFunc“作为props并在仍将工作的子组件中调用此回调时。这仍然是一条很好的路。它的缺点是它不是一种推荐的用法。
想象一下,您将"callbackFunc“传递给许多childs组件。当事情出了问题,很难从哪里找到它被解雇的地方。
在$listeners上直接调用方法也是如此。突然,你的状态改变了,你不知道确切的位置。以及组件什么时候启动了它。
发布于 2020-03-05 22:28:23
使用道具而不是从$emit回调
const LoginForm = {
name: 'Login-Form',
props: {
loading: {
type: Boolean,
default: false,
}
},
template: `
<button :disabled="loading" @click="$emit('some_data')">
<template v-if="loading">Logging you in</template>
<template v-else>login</template>
</button>
`,
};
new Vue({
el: '#app',
components: {
LoginForm,
},
data() {
return {
loadingLoginForm: false,
};
},
methods: {
handleSubmit() {
// Set loading state before async
this.loadingLoginForm = true;
// Some async shish
setTimeout(() => this.loadingLoginForm = false, 1500)
}
}
})<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
<login-Form :loading="loadingLoginForm" @some_data="handleSubmit" />
</div>
https://stackoverflow.com/questions/60554270
复制相似问题