【发布时间】:2019-05-25 18:16:03
【问题描述】:
以下代码,是一个非常简单的 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,该newQuoteTxt 作为quotesRef 下的报价项目添加到Firebase (addQuote())。一旦添加报价(在 firebase 上),Firebase 客户端 SDK 的 value 事件就会触发,并将新报价(通过回调)添加到 localArray (allQuotes)。 VueJS 然后用新添加的 Quote 更新 DOM。
addQuote() 方法的工作方式如下:
- 首先,将回调/侦听器附加到quotesRef 上的“值”事件
quotesRef.on('value', function (snapshot) {
....
})
-
接下来,使用 ID
this.newQuoteIdx创建一个 firebase ref(quotesRef的子代)var newQuoteRef = quotesRef.child(this.newQuoteIdx)
然后(在这个新创建的 Ref 上)调用 set(),将 newquote 添加到 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 事件的侦听器/回调,然后添加代码 newQuoteRef.set({ ... })新报价(在 firebase 上),这反过来会触发 'value' 事件。
我不确定为什么会发生这种情况。 anybuddy 可以解释为什么在创建引号之前调用侦听器/回调。
(QuotesRef 的)子节点是否缓存在客户端,这样即使在添加新报价之前,'value' 也会触发。
谢谢
【问题讨论】:
标签: firebase vue.js firebase-realtime-database vuejs2