Skip to content

Instantly share code, notes, and snippets.

@shar0
Last active January 10, 2017 06:08
Show Gist options
  • Save shar0/7c29947f9c03a3201997389eb7a3222c to your computer and use it in GitHub Desktop.
Save shar0/7c29947f9c03a3201997389eb7a3222c to your computer and use it in GitHub Desktop.
Chat Room : Firebase + VueJS
<!doctype html>
<html>
<head>
<title>Firebase + VueJS</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<script src="//www.gstatic.cn/firebasejs/3.6.4/firebase.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.js"></script>
<script src="//unpkg.com/vuefire@1.3.0"></script>
<style>
* {
padding: 0;
margin: 0;
}
body {
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 15px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: #fff;
color: #0D2C54;
}
ul, li {
list-style: none;
}
label {
color: #7FB800;
}
input[type="text"],
textarea {
width: 250px;
border: none;
background: #ededed;
border-radius: 4px;
color: #666;
padding: 5px;
font-size: 1em;
resize: none;
outline: none;
}
textarea {
height: 90px;
}
input[type="text"]:focus,
textarea:focus {
border-color: #00A6ED;
}
input[type=submit] {
border-radius: 4px;
border: 0;
width: 80px;
height: 25px;
background: #00A6ED;
color: white;
}
.form-row {
margin-top: 10px;
}
.room-selector {
position: fixed;
left: 0;
right: 0;
color: white;
padding: 10px 20px;
background-color: #7FB800;
}
.room-selector label {
color: white;
}
.room-selector label + label {
margin-left: 10px;
}
.message-list {
padding: 10px 20px;
}
.message-list li {
font-size: 1.2em;
}
.message-list li + li {
margin-top: 10px;
}
.message-list .status {
color: #999;
font-size: .8em;
}
.chat-form {
padding: 80px 20px 10px;
}
footer {
padding: 10px 20px;
background: #FFB400;
color: white;
}
</style>
</head>
<body>
<div id="app">
<div is="room-selector" @selected="changeRoom"></div>
<div is="chat-form" :room-id="currentRoomId"></div>
<div is="message-list" :room-id="currentRoomId"></div>
</div>
<footer>基于 Firebase & VueJS</footer>
<script type="text/x-template" id="room-selector-template">
<div class="room-selector">
<h2>
<strong>聊天室</strong>
</h2>
<label v-for="item, key in roomNames">
<input type="radio" v-model="currentRoomId" :value="item['.key']">
<span>{{item[".value"]}}</span>
</label>
</div>
</script>
<script type="text/x-template" id="message-list-template">
<div class="message-list">
<ul>
<li class="item" v-for="item in sortedList">
<div class="message">
<span>{{item["message"]}}</span>
</div>
<div class="status"><b>{{item["name"]}}</b> {{item["timestamp"] | date}}</div>
</li>
</ul>
</div>
</script>
<script type="text/x-template" id="chat-form-template">
<div class="chat-form">
<div class="form-row">
<input id="name" type="text" v-model="name" placeholder="昵称"/>
</div>
<div class="form-row">
<textarea v-model="message" cols="30" rows="10" placeholder="信息"></textarea>
</div>
<div class="form-row">
<input type="submit" @click="newMessage" value="发送">
</div>
</div>
</script>
<script>
// Setup Firebase
var config = {
apiKey: "AIzaSyDdVuy8ffXw0ql3crasRcczy82YeVtC7fU",
authDomain: "frontend-chatroom.firebaseapp.com",
databaseURL: "https://frontend-chatroom.firebaseio.com"
};
var fb = firebase.initializeApp(config);
var roomNamesRef = firebase.database().ref('room_names');
var messagesRef = firebase.database().ref('messages');
Vue.component('room-selector', {
template: '#room-selector-template',
data: function () {
return {
currentRoomId: null
}
},
watch: {
roomNames: function (val, oldVal) {
// Pick up first chat room
if (typeof val !== "undefined" && val.length > 0) {
this.currentRoomId = val[0]['.key'];
}
},
currentRoomId: function (val, oldVal) {
this.$emit("selected", val);
}
},
firebase: {
roomNames: roomNamesRef
}
});
Vue.component('message-list', {
template: '#message-list-template',
props: ["roomId"],
firebase: {
list: messagesRef.child(0)
},
filters: {
date: function (time) {
var theDate = new Date(time);
return theDate.toGMTString();
}
},
computed: {
sortedList: function () {
return this.list.reverse()
}
},
watch: {
roomId: function () {
this.$bindAsArray('list', messagesRef.child(this.roomId).orderByChild("timestamp").limitToLast(25));
}
}
});
Vue.component('chat-form', {
template: '#chat-form-template',
props: ["roomId"],
data: function () {
return {
"message": null,
"name": null
}
},
methods: {
newMessage: function () {
messagesRef.child(this.roomId).push({
message: this.message,
name: this.name,
timestamp: firebase.database.ServerValue.TIMESTAMP
});
this.message = null;
}
}
});
var App = new Vue({
el: '#app',
data: function () {
return {
currentRoomId: null
}
},
methods: {
changeRoom: function (roomId) {
this.currentRoomId = roomId;
}
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment