异步方法中的$ emit-Vue2

时间:2019-01-04 19:56:40

标签: javascript vue.js

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

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')
  }
}

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

最终解决方案

其中一个问题是使用不同的生命周期,这要归功于Evan

另一个问题是异步/等待使用,更改为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
  })
}

它是否已经返回了承诺,因为它与那时链接在一起了……所以令人困惑。

再次进行测试,似乎return在工作,大声笑。

3 个答案:

答案 0 :(得分:2)

我只是建议重组您的方法,因为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)
}

答案 1 :(得分:2)

这里的问题是子组件上的created在父组件上的mounted之前被调用,因此,在您开始Axios调用之后,您就开始收听。

>

created生命周期事件方法对返回的承诺不做任何事情,因此您的方法在开始Axios调用后立即返回,并且其余的vue组件生命周期继续进行。

您应该能够将父级观察结果更改为created事件,以使此工作有效:

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

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

答案 2 :(得分:0)

如果您要实现的目的是告诉直接父级不再加载,则必须像这样发出相同的实例

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.vueroot发出的。

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