在渲染组件之前从 api 获取数据
Fetching data from api before render component
我在呈现页面之前发送了 2 个 api 请求:
const Profile = {
template: '#profile',
attributes: null,
photos: [],
data: function () {
return {attributes: Profile.attributes, photos: Profile.photos};
},
beforeRouteEnter: function (to, from, next) {
function getProfile() {
return axios.get('user/get-profile?access-token=1', {responseType: 'json'});
}
function getPhotos() {
return axios.get('photos?access-token=1', {responseType: 'json'});
}
axios.all([getProfile(), getPhotos()])
.then(axios.spread(function (profile, photos ) {
console.log(profile, photos );
next(vm => {
vm.setProfile(profile);
vm.setPhotos(photos);
})
}));
},
methods: {
setProfile: function (response) {
Profile.attributes = response.data;
console.log(Profile.attributes);
},
setPhotos: function (response) {
Profile.photos = response.data;
console.log(response);
},
}
};
问题是渲染发生在 setProfile
和 setPhotos
方法之前。如何更正渲染我的组件?
您应该能够 return return 通过调用 axios.all 编辑的 Promise,例如:
return axios.all([getProfile(), getPhotos()])
// .then() => ...
或者您可以向数据对象添加一个 属性 并使用它来显示加载器,直到所有 Promises 都已解决
const Profile = {
template: '#profile',
attributes: null,
photos: [],
data: function () {
return {attributes: Profile.attributes, photos: Profile.photos, isLoading: true};
},
beforeRouteEnter: function (to, from, next) {
function getProfile() {
return axios.get('user/get-profile?access-token=1', {responseType: 'json'});
}
function getPhotos() {
return axios.get('photos?access-token=1', {responseType: 'json'});
}
axios.all([getProfile(), getPhotos()])
.then(axios.spread(function (profile, memes) {
console.log(profile, memes);
this.isLoading = false
next(vm => {
vm.setProfile(profile);
vm.setPhotos(photos);
})
}));
},
methods: {
setProfile: function (response) {
Profile.attributes = response.data;
console.log(Profile.attributes);
},
setPhotos: function (response) {
Profile.photos = response.data;
console.log(response);
},
}
};
省略了模板代码,但您可以根据isLoading切换您显示的内容。如果你走这条路,那么最好为加载程序创建一个抽象。
我还建议您查看 vuex 而不是将所有数据耦合到任何特定的组件状态。
如评论中所述,第一个async/await解决方案有点误导,因为所有生命周期方法都是同步的。这是有效的,因为代码被转换为内部带有 IIFE 的同步函数。
下面我添加了一些最近的片段。
旧答案
尝试 async/await。我删除了 beforeRouteEnter
、axios.spread
并添加了 create
.
const Profile = {
template: '#profile',
attributes: null,
photos: [],
data() {
return {
attributes: null,
photos: null,
};
},
async created() {
const getProfile = await axios.get('user/get-profile?access-token=1');
const getPhotos = await axios.get('photos?access-token=1');
this.setProfile(profile);
this.setPhotos(photos);
},
methods: {
setProfile(response) {
this.attributes = response.data;
console.log(this.attributes);
},
setPhotos(response) {
this.photos = response.data;
console.log(response);
},
},
};
更短
const Profile = {
template: '#profile',
attributes: null,
photos: [],
data() {
return {
attributes: null,
photos: null,
};
},
async created() {
this.attributes = await axios.get('user/get-profile?access-token=1');
this.photo = await axios.get('photos?access-token=1');
},
};
更新答案
您可以在生命周期方法中使用异步函数。
const Profile = {
template: '#profile',
attributes: null,
photos: [],
data() {
return {
attributes: null,
photos: null,
};
},
created() {
const fetchData = async () => {
const { data: attributes } = await axios.get(
'user/get-profile?access-token=1'
);
const { data: photos } = await axios.get('photos?access-token=1');
this.attributes = attributes;
this.photos = photos;
};
fetchData();
},
};
Vue 3 和 setup()
在 Vue 3 中你可以使用 async setup()
。如果你使用它,你必须用 Suspense
包装你的组件。警告!此 API 当前 实验性 https://v3.vuejs.org/guide/migration/suspense.html.
<Suspense>
<template #default>
<YourComponent />
</template>
<template #fallback>
<div>Loading ...</div>
</template>
</Suspense>
export default {
name: 'YourComponent',
async setup() {
const { data: attributes } = await axios.get('user/get-profile?access-token=1');
const { data: photos } = await axios.get('photos?access-token=1');
return {
attributes,
photos
}
}
}
也许这可以帮助某人:
尝试 Promise
:
let fetchData = new Promise((resolve, reject) => {
axios.get(YOUR_API)
.then(function (response) {
resolve();
})
.catch(function () {
reject('Fail To Load');
});
});
fetchData.then(
function(success) {
YOUR_SUCCESS_LOGIC
},
function(error) {
console.log(error);
}
);
我在呈现页面之前发送了 2 个 api 请求:
const Profile = {
template: '#profile',
attributes: null,
photos: [],
data: function () {
return {attributes: Profile.attributes, photos: Profile.photos};
},
beforeRouteEnter: function (to, from, next) {
function getProfile() {
return axios.get('user/get-profile?access-token=1', {responseType: 'json'});
}
function getPhotos() {
return axios.get('photos?access-token=1', {responseType: 'json'});
}
axios.all([getProfile(), getPhotos()])
.then(axios.spread(function (profile, photos ) {
console.log(profile, photos );
next(vm => {
vm.setProfile(profile);
vm.setPhotos(photos);
})
}));
},
methods: {
setProfile: function (response) {
Profile.attributes = response.data;
console.log(Profile.attributes);
},
setPhotos: function (response) {
Profile.photos = response.data;
console.log(response);
},
}
};
问题是渲染发生在 setProfile
和 setPhotos
方法之前。如何更正渲染我的组件?
您应该能够 return return 通过调用 axios.all 编辑的 Promise,例如:
return axios.all([getProfile(), getPhotos()])
// .then() => ...
或者您可以向数据对象添加一个 属性 并使用它来显示加载器,直到所有 Promises 都已解决
const Profile = {
template: '#profile',
attributes: null,
photos: [],
data: function () {
return {attributes: Profile.attributes, photos: Profile.photos, isLoading: true};
},
beforeRouteEnter: function (to, from, next) {
function getProfile() {
return axios.get('user/get-profile?access-token=1', {responseType: 'json'});
}
function getPhotos() {
return axios.get('photos?access-token=1', {responseType: 'json'});
}
axios.all([getProfile(), getPhotos()])
.then(axios.spread(function (profile, memes) {
console.log(profile, memes);
this.isLoading = false
next(vm => {
vm.setProfile(profile);
vm.setPhotos(photos);
})
}));
},
methods: {
setProfile: function (response) {
Profile.attributes = response.data;
console.log(Profile.attributes);
},
setPhotos: function (response) {
Profile.photos = response.data;
console.log(response);
},
}
};
省略了模板代码,但您可以根据isLoading切换您显示的内容。如果你走这条路,那么最好为加载程序创建一个抽象。
我还建议您查看 vuex 而不是将所有数据耦合到任何特定的组件状态。
如评论中所述,第一个async/await解决方案有点误导,因为所有生命周期方法都是同步的。这是有效的,因为代码被转换为内部带有 IIFE 的同步函数。
下面我添加了一些最近的片段。
旧答案
尝试 async/await。我删除了 beforeRouteEnter
、axios.spread
并添加了 create
.
const Profile = {
template: '#profile',
attributes: null,
photos: [],
data() {
return {
attributes: null,
photos: null,
};
},
async created() {
const getProfile = await axios.get('user/get-profile?access-token=1');
const getPhotos = await axios.get('photos?access-token=1');
this.setProfile(profile);
this.setPhotos(photos);
},
methods: {
setProfile(response) {
this.attributes = response.data;
console.log(this.attributes);
},
setPhotos(response) {
this.photos = response.data;
console.log(response);
},
},
};
更短
const Profile = {
template: '#profile',
attributes: null,
photos: [],
data() {
return {
attributes: null,
photos: null,
};
},
async created() {
this.attributes = await axios.get('user/get-profile?access-token=1');
this.photo = await axios.get('photos?access-token=1');
},
};
更新答案
您可以在生命周期方法中使用异步函数。
const Profile = {
template: '#profile',
attributes: null,
photos: [],
data() {
return {
attributes: null,
photos: null,
};
},
created() {
const fetchData = async () => {
const { data: attributes } = await axios.get(
'user/get-profile?access-token=1'
);
const { data: photos } = await axios.get('photos?access-token=1');
this.attributes = attributes;
this.photos = photos;
};
fetchData();
},
};
Vue 3 和 setup()
在 Vue 3 中你可以使用 async setup()
。如果你使用它,你必须用 Suspense
包装你的组件。警告!此 API 当前 实验性 https://v3.vuejs.org/guide/migration/suspense.html.
<Suspense>
<template #default>
<YourComponent />
</template>
<template #fallback>
<div>Loading ...</div>
</template>
</Suspense>
export default {
name: 'YourComponent',
async setup() {
const { data: attributes } = await axios.get('user/get-profile?access-token=1');
const { data: photos } = await axios.get('photos?access-token=1');
return {
attributes,
photos
}
}
}
也许这可以帮助某人:
尝试 Promise
:
let fetchData = new Promise((resolve, reject) => {
axios.get(YOUR_API)
.then(function (response) {
resolve();
})
.catch(function () {
reject('Fail To Load');
});
});
fetchData.then(
function(success) {
YOUR_SUCCESS_LOGIC
},
function(error) {
console.log(error);
}
);