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')    
})
Другие вопросы по тегам