以下代码是一个非常简单的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商店)
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
作为addQuote()
下的报价项添加到Firebase(quotesRef
)中。一旦在Firebase上添加了报价,Firebase客户端SDK的value
事件就会触发,并将新的报价(通过回调)添加到localArray(allQuotes
)中。然后VueJS使用新添加的Quote更新了DOM。
addQuote()
方法以下列方式工作:
quotesRef.on('value', function (snapshot) {
....
})
接下来,创建一个ID为quotesRef
的firebase ref(this.newQuoteIdx
的子代)
var newQuoteRef = quotesRef.child(this.newQuoteIdx)
然后调用set()
(在这个新创建的Ref上),将新引用添加到firebase RealTime DB中。
value
事件被触发(从步骤1开始),并调用侦听器/ callback。 回调通过匹配localArr和snap.key
的键在现有项目列表中查找此新引号的键(如果未找到,则将新引号添加到localArr)。 localArr提交到vuex存储。
`vm.$store.commit('set_allQuotes', localArr)`
VueX然后更新该阵列的所有订户组件。然后VueJS将新报价添加到现有报价列表中(更新DOM)
在调试addQuote
方法时,我注意到的问题是,脚本的执行/流(通过chrome调试器中的F8)首先进入代码{之前附加到value
事件的侦听器/回调中{1}}添加了新的报价(在Firebase上),这又将触发“值”事件。
我不确定为什么会这样。 anybuddy能否解释为什么在创建引号之前调用侦听器/回调。
(QuotesRef的)子节点是否缓存在客户端,这样即使在添加新的报价之前也会触发“值”。
谢谢
答案 0 :(得分:1)
如果我正确理解您的问题(您的代码不太容易遵循!:-)),这是正常的行为。如documentation中所述:
值事件将使用存储在以下位置的初始数据一次触发 此位置,然后每次数据再次触发 更改。
您的沙盒演示实际上并未显示该应用程序的工作原理,但是通常您不应该在将新节点保存到数据库的方法中设置侦听器。这两件事应该分开。
一种常见的方法是将侦听器设置在组件的created
钩子中(请参见https://vuejs.org/v2/guide/instance.html#Instance-Lifecycle-Hooks和https://vuejs.org/v2/api/#created),然后在您的addQuote
方法中将其写入数据库。一旦您写完,监听器就会被解雇。