我正在我的firebase数据库中存储我希望显示的每个项目的图像的相对路径。我无法让图像显示在屏幕上,因为我需要异步获取图像。 firebase架构目前如下:
{
items: {
<id#1>: {
image_loc: ...,
},
<id#2>: {
image_loc: ...,
},
}
}
我想在我的页面上显示这些图像,其代码如下:
<div v-for="item in items">
<img v-bind:src="item.image_loc">
</div>
这不起作用,因为我的相对位置指向firebase存储中的一个位置。从这个相对URL获取真实URL的相关代码是:
firebase.storage().ref('items').child(<the_image_loc>).getDownloadURL()
它返回一个带有真实url的promise。这是我目前的vue.js代码:
var vue = new Vue({
el: '.barba-container',
data: {
items: []
},
firebase: function() {
return {
items: firebase.database().ref().child('items'),
};
}
});
我已经尝试使用计算属性,包括使用vue-async-computed,但这些解决方案似乎不起作用,因为我无法传递参数。
基本上,如何显示每个元素需要承诺结果的元素列表?
我能够通过为vue.js使用asyncComputed库并承诺一次下载所有图像来解决这个问题,而不是单独尝试这样做。
/**
* Returns a promise that resolves when an item has all async properties set
*/
function VotingItem(item) {
var promise = new Promise(function(resolve, reject) {
item.short_description = item.description.slice(0, 140).concat('...');
if (item.image_loc === undefined) {
resolve(item);
}
firebase.storage().ref("items").child(item.image_loc).getDownloadURL()
.then(function(url) {
item.image_url = url;
resolve(item);
})
.catch(function(error) {
item.image_url = "https://placeholdit.imgix.net/~text?txtsize=33&txt=350%C3%97150&w=350&h=150";
resolve(item);
});
});
return promise;
}
var vue = new Vue({
el: '.barba-container',
data: {
items: [],
is_loading: false
},
firebase: function() {
return {
items: firebase.database().ref().child('items'),
};
},
asyncComputed: {
processedItems: {
get: function() {
var promises = this.items.map(VotingItem);
return Promise.all(promises);
},
default: []
}
}
});
最后,我需要在我的模板中使用:v-for="item in processedItems"
来渲染带有图像网址的项目
在解析url之前,我能够解决它而没有任何额外的依赖关系而不向数组添加元素:
在我的模板中:
<div v-for="foo in foos" :key="foo.bar">
<img :src="foo.src" :alt="foo.anotherbar">
...
</div>
在我的组件中(例如在mounted()
内)
const db = firebase.firestore()
const storage = firebase.storage().ref()
const _this = this
db.collection('foos').get().then((querySnapshot) => {
const foos = []
querySnapshot.forEach((doc) => {
foos.push(doc.data())
})
return Promise.all(foos.map(foo => {
return storage.child(foo.imagePath).getDownloadURL().then(url => {
foo.src = url
_this.foos.push(foo)
})
}))
}).then(() => {
console.log('all loaded')
})