Vuefire получит Firebase Image Url
Я храню относительные пути к изображениям в моей базе данных 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>
Это не работает, так как мое относительное местоположение указывает на место в хранилище базы огня. Соответствующий код для получения истинного URL из этого относительного URL:
firebase.storage().ref('items').child(<the_image_loc>).getDownloadURL()
который возвращает обещание с истинным URL. Вот мой текущий код vue.js:
var vue = new Vue({
el: '.barba-container',
data: {
items: []
},
firebase: function() {
return {
items: firebase.database().ref().child('items'),
};
}
});
Я пытался использовать вычисляемые свойства, включая использование vue-async-computed, но эти решения, похоже, не работают, так как я не могу передать параметры.
Как мне отобразить список элементов, где каждому элементу нужен результат обещания?
2 ответа
Я смог решить эту проблему, используя библиотеку asyncComputed for vue.js и пообещав загрузить все изображения одновременно, вместо того, чтобы пытаться сделать это по отдельности.
/**
* 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-адресами изображений
Я смог решить ее без каких-либо дополнительных зависимостей, не добавляя элементы в массив, пока не будет разрешен 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')
})