首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >VueJS - $emit和$listeners的区别

VueJS - $emit和$listeners的区别
EN

Stack Overflow用户
提问于 2020-03-05 21:33:33
回答 2查看 986关注 0票数 2

让我们以下面的场景为例,其中WelcomePage (父)使用LoginForm (子)与自定义事件@submit

代码语言:javascript
复制
// WelcomePage.vue
<LoginForm @submit="handleLogin">Login<Button>

然后,组件LoginForm具有以下代码:

代码语言:javascript
复制
// LoginForm
<form @submit.prevent="handleSubmit"> ... </form>
代码语言:javascript
复制
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:

代码语言:javascript
复制
// 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:

代码语言:javascript
复制
// 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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-03-05 22:58:07

在我看来,$emit帮助您保持流量体系结构。您可以很容易地看到数据流,它帮助您调试。

另一方面,使用$listeners被认为是一种不好的做法。这是可以做到的,但它可以破坏单向数据流。同样,对于$root,您仍然可以访问它,但这并不意味着您应该使用(修改)它;-)

然而,使用什么始终取决于上下文和您的需要。只是要小心,一旦破坏了单向数据流,就很难调试。

评论后的编辑:这只是我对它的看法。

当使用props$emit作为组件间通信的推荐方式时。你有一个清晰的数据流。此外,Vue开发工具还可以帮助您跟踪每个$emit,因此您可以一步一步准确地知道发生了什么。

当使用"collbackFunc“作为props并在仍将工作的子组件中调用此回调时。这仍然是一条很好的路。它的缺点是它不是一种推荐的用法。

想象一下,您将"callbackFunc“传递给许多childs组件。当事情出了问题,很难从哪里找到它被解雇的地方。

$listeners上直接调用方法也是如此。突然,你的状态改变了,你不知道确切的位置。以及组件什么时候启动了它。

票数 1
EN

Stack Overflow用户

发布于 2020-03-05 22:28:23

使用道具而不是从$emit回调

代码语言:javascript
复制
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)
    }
  }
})
代码语言:javascript
复制
<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>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60554270

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档