【问题标题】:$emit inside async method - Vue2$emit 在异步方法中 - Vue2
【发布时间】:2019-05-31 09:32:02
【问题描述】:

这是我孩子的组件异步方法:

async created () {
  this.$parent.$emit('loader', true)
  await this.fetchData()
  this.$parent.$emit('loader', false)
}

fetchData 执行 axios get 调用,从 API 获取数据。但是,在 vue-devtools(事件选项卡)中,我只能在更改代码并热重新加载后才能看到事件。我还在父组件中设置了console.log()

mounted() {
  this.$on('loader', (value) => {
    console.log(value)
  })
}

我只能在控制台中看到false。我的目的是将加载器设置为 true(以便我可以显示加载器),然后在获取数据时将其设置为 false。

我的 fetchData 方法:

import http from '@/http'

fetchData() {
  return http.getOffers().then((resp) => {
    this.offersData = resp.data
  })
}

http.js 的内容:

import axios from 'axios'
import config from '@/config'

const HTTP = axios.create({
  baseURL: config.API_URL
})

export default {
  /* calculator */
  getOffers() {
    return HTTP.get('/url')
  }
}

如果我在async created() 中直接使用return axios.get(),那么它可以工作。问题出在这个导入的 http 实例中。

最终解决方案

其中一个问题是使用不同的生命周期,感谢Evan 提到这一点。

另一个问题是 async / await 的使用,更改为 fetchData() 方法:

import http from '@/http'

async fetchData() {
  await http.getOffers().then((resp) => {
    this.offersData = resp.data
  })
}

我必须使这个方法异步并在 axios 请求上使用 await,因为 await 是 thenable,它确实有效。我还在 https.js 中发现了一个问题:

export default {
  /* calculator */
  getOffers() {
    return HTTP.get('/url')
  }
}

它返回HTTP.get(),而不是一个承诺本身,我可以在这里使用then,它会起作用,但是,出于灵活性的目的,我没有这样做。

但是,我仍然不明白为什么它不起作用:

fetchData() {
  return http.getOffers().then((resp) => {
    this.offersData = resp.data
  })
}

它不是已经返回了一个承诺,因为它与 then 链接在一起......所以令人困惑。

再次重新测试,似乎return 工作正常,哈哈。

【问题讨论】:

  • 异步方法中的 console.log(this) 是否返回 Vue 对象或承诺?
  • 你能创建一个 JSFiddle 吗?
  • @KubwimanaAdrien,我刚刚做了console.log(this) 而不是console.log(value) 并得到了Vue 对象。
  • 小心.catch这将抑制您在.then 回调中获得的所有错误。最好在 .then 的第二个参数中执行:axios.get('/url').then((resp) => {}, (err) => {})infographic

标签: javascript vue.js


【解决方案1】:

我只是建议重组你的方法,因为 axios 本身就是异步方法,所以实际上不需要创建异步方法。

如果您已经定义了 fetchData 方法,并且目标是在进行调用时切换加载器状态,那么应该这样做。

fetchData () {
    this.$parent.$emit("loader", true)

    axios.get(url)
        .then(resp => {
            this.data = resp
            this.$parent.$emit("loader", false)
        })
}

当然这些 then 语句可以合并为一个,但思路是一样的。

编辑:(使用父发射函数)

fetchData () {
    this.loader = true

    axios.get(url)
        .then(resp => this.data = resp)
        .then(() => this.loader = false)
}

【讨论】:

  • 谢谢,但这不是我的情况,因为 loader 本身在父组件中,否则我当然会在 axios Promise 中使用它。
  • 我明白了。如果不是调用 emit,同样的事情不会起作用吗?
  • 它在 axios promise 中工作,但我想使用 async / await 使其工作 :)
【解决方案2】:

如果您要达到的目的是告诉直接父级它不再加载,则必须像这样向同一个实例发射

async created () {
  this.$emit('loader', true)
  await this.fetchData()
  this.$emit('loader', false)
}

通过删除$parent,您将从当前组件发出。

--Root
 --My-page.vue
   -Some-child.vue

现在您将从some-child.vue 发射到my-page.vue。我没有尝试过,但理论上你通过父级发射来做什么:(this.$parent.$emit('loader', false)) 你是从my-page.vue 发射到root

因此,如果您在组件上有 $on@loader,如下所示:<Some-child @loader="doSomething"/>,由于您从父级发射,这将永远不会运行。

【讨论】:

  • 假设我在 Some-child 中有一个 $emit,我正在使用 this.$on 收听我的页面中的 $emit,因为 this.$on$emit 一起使用仅在同一个 Vue 实例中,这就是我使用 this.$parent.$emit 的原因。
  • 哦,对了。这似乎是一种解决方法,或者?我自己没有用过$。但是,我倾向于将侦听器添加到自定义元素,如上所示。我可能错了,但在我看来,在 $parent 上做事似乎很脏,因为将来,父母可能会改变。
  • 似乎 Vue 允许使用 $on$emit 作为替代方案。在什么情况下您使用$on?我希望 Vue 会变得固执己见,就像 Angular 一样,所以应该只有一种方法可以使东西正常工作。
  • 是的,你是对的。我刚刚再次浏览了文档以刷新我的记忆。当我想使用$on 时,我个人无法找到一个好的用例。但是,有一个here。我相信发出数据的“正常”方式是使用v-on: / @ way
【解决方案3】:

这里的问题是子组件上的created 在父组件上的mounted 之前被调用,所以你在开始Axios 调用之后才开始监听。

created 生命周期事件方法不会对返回的 Promise 执行任何操作,因此您的方法会在您开始 Axios 调用后立即返回,并且 vue 组件生命周期的其余部分将继续。

您应该能够将您的父观察更改为 created 事件以使其工作:

created() {
  this.$on('loader', (value) => {
    console.log(value)
  })
}

如果由于某种原因您需要做一些在created 中无法访问的操作,例如访问$el,我建议将两者都移至mounted 生命周期挂钩。

【讨论】:

  • 聪明,我没发现第二个挂载的!
  • 好消息,现在我的console.log(value) 会同时触发truefalseasync 现在出了点问题。
  • 太好了,这就是你想要的,对吧?假设 fetchDatatruefalse 之间做了一些事情
  • 它们应该是true & false,同步的,例如:设置loader为true,然后获取数据,当获取数据时,设置loader为false。但现在它同时是真假,
  • 谢谢!我认为你的问题是你会想要return 的承诺。因此,将您的声明更改为:return axios.get(url) 而不是 axios.get(url)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-04
  • 2016-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多