Существует ли стандартный/изящный способ достижения огнезащитных реактивных объектов без Firebase?

То, что мне нравится в базах данных реального времени, таких как Firebase, - это их функции push. например, vuefire делает невероятно простым обладание самообновляющимися объектами без навязывания сотен прослушивателей сокетов и обратных вызовов.

Это пример:

data(){
  return {
    books: []
  }
},

created(){
  axios.get('/books', (books) => {
    this.books = books
  })
}

Чтобы добавить db-реактивность к этому, мне нужно как минимум 3 события "созданная книга", "обновленная книга", "снятая книга".

Pusher.on('book-created', (book) {
  this.books.push(book)
})
Pusher.on('book-updated', (book) {
  let b = _.find(this.books, {id: book.id})

  if(b){
   _.extend(b, book)
  } 
})
etc..

Он становится довольно волосатым, когда у вас много моделей и много просмотров, у некоторых видов есть другой набор книг, поэтому я не могу иметь только одну стандартную переменную vuex. Есть ли разумный/быстрый способ приблизиться к этому?

Я могу, конечно, абстрагировать отправку события на моем бэкэнд, чтобы все мои модели автоматически активировали события. но интерфейс не смущен.

Ответ 1

Раньше я никогда не работал с толкателем, и я не знаю точно, что такое "разные книги", о которых вы говорите, но я думаю, что могу дать вам некоторую отправную точку, чтобы сделать ваш код немного более элегантным.

Первое, что я предлагаю; не пытайтесь изобрести колесо, используйте компоненты mixins. Просто создайте mixin, как обычно, вы будете использовать свой backend, чтобы он работал с некоторыми динамическими параметрами (которые вы можете установить в data() компонента data()) и импортировать их на каждый компонент, который вам нужен той же функциональности, с различными параметрами.

Пример (вам нужно будет соответствующим образом адаптировать его)

// Create an ES6 module and export this function, or the whole mixin
// (in that case export the mixin instead)
const initPusher = function ({pusher, collection, key, events}, component) {
  collection = component[collection]

  pusher.on(events.created, (record) => {
    collection.push(record)
  })

  pusher.on(events.updated, (record) => {
    let r = _.find(collection, {[key]: record[key]})

    if(r){
     _.extend(r, record)
    } 
  })
}

const PusherMixin = {
  methods: {
    // You can add some common methods for all your
    // components making use of this mixin
  },
  created () {
    initPusher(Object.assign({}, {
      pusher: Pusher,
      collection: 'collection',
      key: 'id',
      events: {
        created: 'book-created',
        updated: 'book-updated'
      }
    }, this.pusherOptions), this)
  }
}

new Vue({
  el: "#app",
  mixins: [PusherMixin],
  data () {
    return {
      books: [],
      pusherOptions: {
        collection: 'books',
        key: 'id',
        events: {
          created: 'book-created',
          updated: 'book-updated'
        }
      }
    }
  }
})

Мое второе предложение подразумевало прототип управляемого манипулятора с некоторыми пользовательскими методами и крючками для запуска событий и XHRequests, но после завершения кода для mixin я выяснил, что расширение прототипа массива с большим количеством методов добавило слишком много сложностей, и хороший mixin был совершенно противоположное этому.

Если вы хотите пойти глубже, вы можете взглянуть на RxJS и наблюдаемые. Вы можете создать что-то поверх этого с помощью Pusher, чтобы получить что-то вроде объекта реального времени Firebase.