I am "discovering" Firebase and I'm trying create simple chat with Vue, Vuex and Firebase. But because I'm just starting out with Vue, I need code review or advices from more experienced programmers. I need to know whether this code is properly structured - if it is well written in "Vue way" - and how to make my components better - more universal / better separated from rest of the code.
var uid = null
var firebaseConfig = {
apiKey: "AIzaSyDGYiab8xoIXIgbFSmLSwXubNL2T3Rr6AQ",
authDomain: "first-steps-6abb2.firebaseapp.com",
databaseURL: "https://first-steps-6abb2.firebaseio.com"
}
var store = new Vuex.Store({
state: {
messages: []
},
mutations: {
addMessage (state, message) {
state.messages.push(message)
if (state.messages.length > 10) {
state.messages.shift()
}
}
}
})
var listMessages = {
template: `
<ul class="list-messages">
<li v-for="message in messages">
<span>{{message.time}}</span> {{ message.text }}
</li>
</ul>
`,
data () {
return {
messages: this.$store.state.messages
}
}
}
var addMessage = {
template: `
<div class="add-message">
<label for="message">Add new:</label>
<input id="message" @keyup.enter v-model="message">
<button @click="sendMsg">Send</button>
</div>
`,
data () {
return {
message: ''
}
},
methods: {
sendMsg () {
messages.push().set({
uid: uid,
content: this.message,
timestamp: firebase.database.ServerValue.TIMESTAMP
})
this.message = ''
}
}
}
firebase.initializeApp(firebaseConfig)
firebase.auth().signInAnonymously()
firebase.auth().onAuthStateChanged(function (user) {
if (user) { uid = user.uid }
})
new Vue({
el: '#app',
store,
components: {
listMessages,
addMessage
}
})
var db = firebase.database()
var messages = db.ref('messages')
var query = messages.orderByChild('timestamp').limitToLast(10)
query.on('child_added', function (data) {
store.commit('addMessage', {
uid: data.val().uid,
text: data.val().content,
time: moment(data.val().timestamp).format('hh:mm:ss')
})
})
html, body {
margin: 0;
height: 100%;
}
.container {
min-height: 100%;
position: relative;
}
.list-messages {
position: absolute;
box-sizing: border-box;
width: 100%;
top: 10px;
margin: 0;
padding: 10px;
list-style: none;
}
.list-messages span {
color: lightblue;
}
.add-message {
text-align: center;
position: absolute;
width: 100%;
bottom: 10px;
}
<div id="app" class="container">
<list-messages></list-messages>
<add-message></add-message>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.1/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/2.3.1/vuex.min.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.1.3/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.1.3/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.1.3/firebase-database.js"></script>
1 Answer 1
The code looks pretty straight-forward and I don't spot any obvious simplifications. I would suggest that you add error handling - especially for the case when uid
is not null
and remains that way. Perhaps an error message should be added if the request for the appropriate value fails.
Since ecmascript-6 is used (e.g. with the template literals) const
could be used instead of var
for any variable that doesn't get re-assigned (e.g. the components, db
, etc.) and let
for other variables (e.g. uid
).
You could also consider providing a key attribute on the v-for
where the messages are displayed, but the markup is quite simple for those so it may not add any benefit.
It is recommended to provide a
key
withv-for
whenever possible, unless the iterated DOM content is simple, or you are intentionally relying on the default behavior for performance gains.1
1https://v2.vuejs.org/v2/guide/list.html#key