preface

I am Jiang, here I am again, first of all to say that it is really not clickbait, but some time ago to seevue2Source code, found in the source directory there is a calledexamplesFolder, especially large with VUE write smalldemoWe have to go in there anyway.

Then I found the inspiration for the birth of this articledemo: Firebase based shared mailbox demoNow I can’t sit still. If this is used to implement a simple real-time chat function, much more beautiful ah! So there’s the following.

Here is a simple one that I implemented and deployedThe chat room

Few words saidHi, ha, ha, ha! Chicken soup!

start

The role of firebase

First, before implementing it, you need to understand what Firebase is for. Firebase is a cloud database service supported by Google. Unlike regular cloud databases, Firebase can share real-time databases.

Readers who do not have a Google account can register a Google account first

Once registered, you can go directly to the Firebase website

Create the Firebase project

So let’s go straight to the next step.

This is just a demo, so we will not configure Google Analytics, the author can configure it if necessary, generally is statistical analysis traffic and so on.

The next step is to create a Realtime Database.

Here we choose the nearest Singapore server

We’ll start in test mode for the convenience of testing

Create default data

Note that Firebase does not store database-like phenotypic structure data, but json data to ensure real-time transmission! And our chat data can also create an array object to store.

Creating a scaffold project

At this stage, I can officially start the project construction. Here, I directly use my own scaffolding to download the project template construction. If you’re interested, check out the previous article: Create your own scaffolding

Of course, vue-CLI scaffolding can also be used, but I won’t go into details.

create-cli
Copy the code

The current project has the following directory level:

|- page // Project page| - | - index//index page file| - | -- - | -- -static // Resource files| | -- - | -- - | -- - | - CSS | -- - | -- - | - img | - | -- - | -- - | - js | - index. The HTML/ / HTML page
Copy the code

Download the dependent

 npm i firebase --save 
Copy the code

Then create a firebase.config.js file in the js folder to configure the Firebase initialization configuration object and so on.

Firebase.config.js configuration file

Go back to the Firebase website

Click Create Web application

This means importing initialization functions and generating firebase configuration objects, respectively

Copy this code into the firebase.config.js file

Import firebase from ‘Firebase ‘; import firebase from’ Firebase ‘; This way.

The introduction offirebasecode

Here’s our version using V9

import {initializeApp} from  'firebase/app';
import {getDatabase,ref,onValue,push} from 'firebase/database'

const firebaseConfig = {
    apiKey: "AIzaSyCL59rWYn4qI40MOa55PFud-6dn-KtkiYc".authDomain: "chatdemo-aa281.firebaseapp.com".databaseURL: "https://chatdemo-aa281-default-rtdb.asia-southeast1.firebasedatabase.app".projectId: "chatdemo-aa281".storageBucket: "chatdemo-aa281.appspot.com".messagingSenderId: "771306835282".appId: "1:771306835282:web:de5dda7d19acc99a3bfe8b"
};
Copy the code
parameter instructions
getDatabase Getting a database reference
ref("xxx/xxx") Returns a reference to the query location
onValue Listen for data changes at a particular location
push If you provide a value push (), that value will be written to the generated location. If no value is passed, nothing is written to the database, and the child content remains empty (but Reference can be used elsewhere).

Initialize thefirebase

initializeApp(firebaseConfig);
Copy the code

createwebsocketConnecting to a Real-time database

const database=getDatabase();
const  chatsRef = ref(database,'chatList'); // Returns a reference to the chat information location
Copy the code

Writing a submission function

/*** * submission function, used to determine the submission of information conforming to the rule *@param NickName nickName *@param ChatContent Indicates the chat information *@param ChatDate Send date */
const chatSubmit = (nickName,chatContent,chatDate) = > {
    if (nickName.length == 0) {
        alert("Nicknames can't be empty!");
        return ;
    }else if(chatContent.trim() == ""){
        alert("Content cannot be empty!");
        return ;
    }else if(chatContent.length > 200 ){
        alert("Exceeding the maximum word count!");
        return ;
    } else{
        pushChatData(nickName,chatContent,chatDate)
    }
}
/*** * Add chat messages to firebase *@param NickName nickName *@param ChatContent Indicates the chat information *@param ChatDate Send date */
const pushChatData =(nickName,chatContent, chatDate) = >{
    push(chatsRef,{
        chatContent,
        chatDate,
        nickName,
    })
}
Copy the code

export

export {chatsRef , chatSubmit ,onValue }
Copy the code

ChatsRef stands for chat REF connection, which is used to retrieve chat list data from the outside via onValue.

Index.js entry file

Instead of creating the index.js file in the scaffolding I use, the reader can create an index.js file at the same level and import the code

import {chatsRef,chatSubmit,onValue} from './firebase.config' // Import the Firebase configuration
Copy the code

The introduction of Vue

Download the dependent

npm install vue --save 
Copy the code

The introduction of Vue

Note here that we cannot import Vue from ‘Vue’ by default, so importing Vue is a version that does not contain the compiler by default and will not compile labels properly on the page! So let’s introduce the full import Vue from ‘Vue /dist/ Vue’

Refer to the Vue documentation: Explanations for different builds

Introduce Vue in index.js

import Vue from 'vue/dist/vue'
Copy the code

Create a Vue instance

el:"#index".// Define the instance ID
data: {state: {
            chatsList: [].// Chat message data
            prpoverVisible: false.// bubble control
            spinning: true.// Load control
        },
        userState: {
            nickName: ""./ / nickname
            chatContent: "".// Information content
            nickCheckStatus: 0.//0 indicates blank, 1 illegal, 2 qualified, and 3 Verification succeeded}},Copy the code

I’m going to add a logical function, which basically includes,

Global profile logic

Initialization If the user has previously entered a nickname will be recorded in localStorage, and will be retrieved to verify the validity of the nickname. If it makes sense, start a conversation.

And make sure that when information changes, the list box that displays the overall information is always at the bottom. As well as date conversion and pre – and post-space merge.

methods:{
  /*** * Initialize * Obtain the local storage nickname. If no, forcibly set */
   init(){
        let nickName=localStorage.getItem('nickName');
        if (nickName == null) return ;
      if (this.checkNickName(nickName)) {
            this.userState.nickName = nickName;
            this.userState.nickCheckStatus = 3; }},/*** * Verify that the nickname passes *@param NickName nickName *@returns {string|*|void|undefined} Verify by returning the name, not by returning an empty string, used for direct judgment. * /
   checkNickName(nickName){
            let checkRule=new RegExp(/ ^ [\ u4e00 - \ u9fa5_a - zA - Z0-9 -] {8} 2 $/);
            let checkValue=nickName.replace(/\s/g."");
            if(! checkValue.length) {this.userState.nickCheckStatus=0;
                return ' ';
            }else if (checkRule.test(checkValue)) {
                this.userState.nickCheckStatus=2;
                return checkValue;
            }else{
                this.userState.nickCheckStatus=1;
                // This is illegal in case someone changes the nickname directly through the browser application
                // Do illegal emptying
                window.localStorage.removeItem('nickName');
                return ' '; }},/**
     * 添加昵称
     */
    addNickName(){
        if (this.checkNickName(this.userState.nickName)) {
            localStorage.setItem('nickName'.this.userState.nickName);
            this.init(); }},/*** * Empty the input field and remove Spaces */
    clearChatContent(){
        this.userState.chatContent="";
        this.userState.chatContent=this.userState.chatContent.replace(/\s/g."");
    },
    /** * convert year month day *@param date
     * @param fmt
     * @returns {*|void|string}* /
    dateShow(date,fmt){
        let o = {
            "M+" : date.getMonth()+1./ / in
            "d+" : date.getDate(),                    / /,
            "h+" : date.getHours(),                   / / hour
            "m+" : date.getMinutes(),                 / / points
            "s+" : date.getSeconds(),                 / / SEC.
            "q+" : Math.floor((date.getMonth()+3) /3), / / quarter
        };
        if(/(y+)/.test(fmt)) {
            fmt=fmt.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length));
        }
        for(var k in o) {
            if(new RegExp("("+ k +")").test(fmt)){
                fmt = fmt.replace(RegExp. $1,RegExp.$1.length==1)? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length))); }}return fmt;
    },
    /** * Add chat *@param e* /
    addChats(e){
        event.cancelBubble=true; // Disallow line breaks
        event.preventDefault();
        event.stopPropagation();
        this.userState.chatContent = this.userState.chatContent.trim();
        chatSubmit(this.userState.nickName,this.userState.chatContent,this.dateShow(new Date(),"yyyy/MM/dd hh:mm:ss"));
        this.clearChatContent();
    },
    /** * becomes the bottom *@returns {Promise<void>}* /
    async scrollToEnd(){
        await this.$nextTick();
        this.$refs.chatMedia.scrollTop = this.$refs.chatMedia.scrollHeight; }},Copy the code

Created creates a listener and initialization function for chat message updates

created(){
    onValue(chatsRef,(snapshot) = >{
        this.state.chatsList = snapshot.val();
        if(this.state.spinning) this.state.spinning=false;
        this.scrollToEnd();
    })
    this.init();
}
Copy the code

Index.html page

Create two areas respectively: chat message display area and input area

<div id="index">
    <div class="norem-index">
        <div class="chat">
            <h3 class="chat-title">LiveChat chat room</h3>
            <! -- Chat message display area -->
            <! -- Input field -->
        </div>
    </div>
</div>
Copy the code

Chat message display area

<div class="chat-media" ref="chatMedia">
    <div class="media"  v-for="item in state.chatsList">
        <div class="media-body">
            <p class="media-heading">
                {{ dateShow(new Date(item.chatDate),"yyyy/MM/dd hh:mm:ss") }}
                <span class="media-name">{{item.nickName}}</span></p>
            <p class="media-content">
                {{item.chatContent}}
            </p>
        </div>
    </div>
</div>
Copy the code

Input area

<div class="enter">
    <! -- Here is responsible for the first time to fill in, normally do not fill in nickname do not let input -->
    <div class="init-enter"  v-if="userState.nickCheckStatus ! = = 3">
        <input class="nick-input" v-model="userState.nickName" @change="checkNickName(userState.nickName)" placeholder="For the first time, please set your nickname ~"/>
        <button  :disabled="userState.nickCheckStatus ! = = 2" @click="addNickName">Start chatting!</button>
    </div>
    <div class="enter-main" v-if="userState.nickCheckStatus === 3">
        <textarea
                class="textarea-enter"
                v-model="userState.chatContent"
                placeholder="Do you have anything to say? Enter to send"
                :rows="5"
                @keydown.enter.stop="addChats"
        />
    </div>
</div>
Copy the code

Here is just a demonstration, the style is not posted here, the author will post the following github address used to view the source code.

Here is the process: when the user needs to come in, first enter a nickname, verify that the nickname is reasonable, and then chat. Since then, we’ve actually been able to view the page, and have implemented the basic chat function.

expand

The above is just a simple chat in advance, but how can the chat only have text? Some emojis will be added as the expression library below to increase the playability of our chat.

Add emojiList firebase

Start by adding the emojiList field in Firebase Realtime Database

Note that it must be stored as an array, not a string, otherwise it will result in emoji garbled characters

Firebase. Config. Js joining emoji

Gets the entry location of the emoji

const emojiRef = ref(database,'emojiList'); // Returns a reference to the query location
Copy the code

export

Add emojiRef to emoji location export

export {chatsRef ,emojiRef , chatSubmit ,onValue }
Copy the code

Index.js adds emoji logic

State is added to the data object of the Vue instance

State: {emojiList: [],// Emoji set prpoverVisible: False,// Bubble control},Copy the code

Click the corresponding emoji in the methods function and add it to the input box, and close the emoji box.

/** * emoji click add *@param item* /
emojiAddChat(item){
    this.userState.chatContent+=item;
    this.state.prpoverVisible=false;
},
Copy the code

The Created lifecycle adds listening for changes to emoji data. To ensure that we only need to update the database of emojiList user emoticons will change in real time

onValue(emojiRef,(snapshot) = >{
    this.state.emojiList = snapshot.val();
})
Copy the code

Index.html added to the emoji display area

Find the input field we added earlier

<div class="enter-main"> 
Copy the code

Adding the following code is mainly to traverse the emojiList obtained and add the emoji selection icon in the upper layer of the input box.

<div class="menu">
    <div>
        <div class="menu-tip" v-show="state.prpoverVisible">
             <span class="menu-emoji" @click="emojiAddChat(item)"  v-for="item in state.emojiList">
                {{item}}
             </span>
        </div>
        <img class="emoji"  @click="()=>{state.prpoverVisible=! state.prpoverVisible}" src="https://www.emojiall.com/favicon.ico"/>
    </div>
</div>
Copy the code

So far emoji has also joined the success.

conclusion

This allows us to implement a simple live chat, which allows us to implement more interesting functions based on the above API. Such as login, online number, online list, discussion of senior agents and so on.

Finally, I leave the author’s work address here, which includes the V8 demo and the V9 demo

I hope you can point star to support the author. I will bring you a better article later! Work together and progress together, I am Jiang!