这是我孩子的组件异步方法:
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
在工作,大声笑。
答案 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.vue
到root
发出的。
因此,如果您在组件上有$on
或@loader
,例如<Some-child @loader="doSomething"/>
,由于您从父级发出,这将永远不会运行。