Следующий код - очень простое приложение Firebase - VueJS, ( codeSandBox demo )
app.vue
<template>
<div class="container">
<!-- Adding Quote -->
<add-quote/>
<!-- Display Quotes -->
<quote-list/>
</div>
</template>
<script>
import addQuote from "./components/AddQuote.vue";
import quoteList from "./components/QuoteList.vue";
export default {
components: {
addQuote,
quoteList
},
methods: {
get_allQuotes: function() {
// var vm = this;
var localArr = [];
quotesRef
.once("value", function(snapshot) {
snapshot.forEach(function(snap) {
localArr.push({
key: snap.key,
category: snap.val().category,
quoteTxt: snap.val().quoteTxt
});
});
})
.then(data => {
this.$store.commit("set_allQuotes", localArr);
});
}
},
mounted() {
this.get_allQuotes();
console.log("App: mounted fired");
}
};
</script>
store.js (vuex store)
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
quotesList: []
},
getters: {
get_quotesList(state) {
return state.quotesList;
}
},
mutations: {
set_allQuotes(state, value) {
state.quotesList = value;
}
}
});
AddQuote.vue
<template>
<div class="row quote-edit-wrapper">
<div class="col-xs-6">
<textarea v-model.lazy="newQuoteTxt"
rows="4"
cols="50"></textarea>
<button @click="addQuote">Add Quote</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
newQuoteTxt: '',
}
},
computed: {
allQuotes() {
return this.$store.getters.get_quotesList;
},
newQuoteIdx() {
var localArr = [...this.allQuotes]
if(localArr.length > 0) {
var highestKEY, currKEY
localArr.forEach((element, idx) => {
currKEY = parseInt(element.key)
if(idx == 0) {
highestKEY = currKEY
} else {
if(highestKEY < currKEY) {
highestKEY = currKEY
}
}
})
return highestKEY + 1
} else {
return 1
}
}
},
methods: {
// ADD new Quote in DB
addQuote: function() {
var vm = this
var localArr = [...this.allQuotes]
//1. First attach 'value' event listener,
// Snapshot will contain data from that ref
// when any child node is added/updated/delete
quotesRef.on('value', function (snapshot) {
snapshot.forEach(function(snap) {
var itemExists = localArr.some(function (item, idx) {
return item.key == snap.key
})
// If newly added item doesn't yet exists then add to local array
if (!(itemExists)) {
localArr.push({
key: snap.key,
category: snap.val().category,
quoteTxt: snap.val().quoteTxt })
vm.$store.commit('set_allQuotes', localArr)
}
})
})
//2. Second set/create a new quotes in Firebase,
// When this quote gets added in Firebase,
// value event (attached earlier) gets fired
// with
var newQuoteRef = quotesRef.child(this.newQuoteIdx)
newQuoteRef.set({
category: 'motivation',
quoteTxt: this.newQuoteTxt
})
}
}
}
</script>
quoteList.vue
<template>
<div class="row">
<div class="col-xs-12 quotes-list-wrapper">
<template v-for="(quote,idx) in allQuotes">
<!-- Quote block -->
<div class="quote-block-item">
<p class="quote-txt"> {{quote.quoteTxt}} </p>
</div>
</template>
</div>
</div>
</template>
<script>
export default {
computed: {
allQuotes() {
return this.$store.getters.get_quotesList;
}
}
}
</script>
Примечание: Основной код концерна: addQuote.vue
Пользователь вводит newQuoteTxt
, который добавляется в Firebase (addQuote()
) как элемент цитаты под quotesRef
. Как только цитата добавляется (на firebase), запускается событие value
SDK на стороне клиента Firebase, и добавляется новая цитата (с помощью обратного вызова) в localArray (allQuotes
). Затем VueJS обновляет DOM недавно добавленной цитатой.
Метод addQuote()
работает следующим образом:
- Сначала присоедините функцию обратного вызова / прослушиватель к событию 'value' в quotesRef
quotesRef.on('value', function (snapshot) {
....
})
Далее создается ссылка на базу данных (дочерний элемент quotesRef
) с идентификатором this.newQuoteIdx
var newQuoteRef = quotesRef.child(this.newQuoteIdx)
Затем вызывается set()
(на этом вновь созданном Ref), добавляющее новую цитату в базу данных RealTime Firebase.
value
событие запускается (присоединяется с шага 1) и вызывается прослушиватель / обратный вызов.
Обратный вызов ищет ключ этой новой цитаты в существующем списке элементов, сопоставляя ключи localArr, и snap.key
, если не найден, добавляет новую цитату в localArr. localArr фиксирует в хранилище vuex.
`vm.$store.commit('set_allQuotes', localArr)`
Затем VueX обновляет все компоненты подписчика этого массива. Затем VueJS добавляет новую цитату в существующий список цитат (обновляет DOM)
При отладке метода addQuote
я заметил проблему, при которой выполнение / поток сценария (через F8 в chrome-отладчике) сначала входит в слушатель / обратный вызов, присоединенный к событию value
, перед кодом newQuoteRef.set({ ... })
, который добавляет новая цитата (на базе Firebase), которая, в свою очередь, вызовет событие 'value'.
Я не уверен, почему это происходит. Может ли кто-нибудь объяснить, почему слушатель / обратный вызов вызывается до создания кавычек.
Кэшируются ли дочерние узлы (из QuotesRef) на стороне клиента, так что значение запускается даже до добавления новой цитаты.
Спасибо