用 Vue.js + Firebase 製作即時聊天功能

這幾天在練習用vue & firebase刻一個仿line即時同步聊天的功能,
直接初體驗vue.js + firebase + webpack三種願望一次滿足XD!

update: 20170923更新
[用 Vue.js + Firebase 製作即時聊天功能(2) - storage]
(https://guahsu.io/2017/09/vue-firebase-realtime-line-chat-2-storage/)

>DEMO<

>原始碼-GitHub<

這幾天想到就會再稍微更新,GitHub與下方文章可能會略有不同

環境設定步驟

  1. 首先安裝node.js,理論目前的版本都會有內建npm了。

    下載位置:https://nodejs.org
    可以透過node -vnpm -v來查證是否已安裝完成node與npm。

  2. 安裝vue-cli,透過指令npm install --g vue-cli安裝。

    可以透過vue -V來查證是否已安裝完成(-V是大寫唷)。

Vue-cli & webpack

  1. 先起一個資料夾來存放專案,並進入該資料夾內,
  2. 接著建立專案,透過vue-cli可以透過指令直接建立一包專案,
    這裡我們使用指令vue init webpack來建立webpack的專案包。

    安裝vue-cli後,可以在命令列下vue list列出可用的template
    建立專案使用vue init <template>這次用到的是webpack。

  3. 建立設定項目:[]<方框內的是我的設定選項
    123456789
    ? Generate project in current directory? //建於當前資料夾[Yes]? Project name (folder_name) //專案名稱,注意需小寫 [自訂專案名稱]? Project description A Vue.js project //專案描述 [自訂描述]? Author //作者,預設抓當前環境git user [自訂]? Vue build standalone [Enter]? Install vue-router? //安裝vue-router [Yes]? Use ESLint to lint your code? [No]? Setup unit tests with Karma + Mocha? [No]? Setup e2e tests with Nightwatch? [No]
  4. 當環境建立好後,輸入指令npm install使相依套件都下載到當前專案中
  5. 主要目錄結構:
    12345678910
    |- build (webpack的設定檔)|- config (專案設定檔)|- dist (編譯後產出的位置)|- src (專案程式碼目錄)  |- assets (其他 css, js, images)  |- components (主要 vue 元件)  |- router (vue 的路由器)  |- App.vue (主要樣版檔)  |- main.js (vue js 主檔案)|- index.js 靜態首頁(進入點)

Firebase

  1. 建立一個專案
  2. 將Firebase的連結資訊複製起來
  3. 進入Database
  4. 修改權限並發布

vue-router設定

  1. 到index.html把firebase剛才複製的那串載入至head中
  2. 到router/index.js修改程式:
    vue-router是vue的路由器,備註內部使用方式如下:
    12345678910111213141516171819
    import Vue from 'vue'import Router from 'vue-router'
    
    import ChatRoom from '@/components/ChatRoom'
    
    Vue.use(Router)export default new Router({  routes: [    {      //路徑用於網址列      path: '/',      //name用於設定連結,例如樣板頁中可用下面方式來寫連結,就不用寫<a>掛path了      //<router-link :to="{ name: 'ChatRoom' }>ChatRoom Page</router-link>      name: 'ChatRoom',      //到這個ChatRoom(/)時,使用ChatRoom元件      component: ChatRoom    }  ]})

而routes內是陣列包覆物件,所以要再新增一個就只要透過逗號(,)的物件新增方式即可,
而router的結果都會被呈現在<router-view></router-view>中(參考main.js)。

在我的程式碼中,Hello已被替換為ChatRoom(預設範例為Hello)
其實這個練習中目前並沒有實際用到router的功能,因為僅載入一頁XD。
詳細設定可參閱官方文件vue-router 2官方文件

流程

  1. 輸入使用者名稱後才能發文
  2. 然後自己的發文是綠底,其他人是灰色(跟line一樣)
  3. 就這樣XD
  4. (傳圖功能請參考第二篇->用 Vue.js + Firebase 製作即時聊天功能(2) - storage)

主程式撰寫ChatRoom

  1. 到components/ChatRoom.vue(預設是Hello.vue我改名了)
  2. HTML與JS都有用到vue的寫法,我將撰寫的程式已備註如下:
    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
    <template>  <div class="container">    <!-- 區塊:name area -->    <div class="name">      <h3>Name:{{ userName }}</h3>      <!-- 註解:使用@click來偵測click,觸發時執行method中的setName() -->      <div class="reset" @click="setName()">Reset Name</div>    </div>    <!-- 區塊:chat room -->    <div class="chatRoom">      <!-- 區塊:head -->      <div class="roomHead">        <div class="roomHead__topButtons">          <div class="roomHead__button close"></div>          <div class="roomHead__button minimize"></div>          <div class="roomHead__button zoom"></div>        </div>        <img src="https://lorempixel.com/50/50/" class="roomHead__img" draggable="false">        <div class="roomHead__title">Test Room</div>      </div>      <!-- 區塊:body -->      <div id="js-roomBody" class="roomBody">        <!-- 註解:使用template來當迴圈容器,或是判斷用的容器,當條件達成時產出template內容 -->        <template v-for="item in messages">          <!-- other people -->          <template v-if="item.userName != userName">            <div class="messageBox">              <img src="https://lorempixel.com/40/40/" class="messageBox__img" draggable="false">              <div class="messageBox__content">                <!-- 註解:Vue使用雙花括號{{}}來顯示script中data:的資料 -->                <div class="messageBox__name">{{item.userName}}</div>                <div class="messageBox__text">{{item.message}}</div>              </div>              <div class="messageBox__time">{{item.timeStamp}}</div>            </大专栏  用 Vue.js + Firebase 製作即時聊天功能ss="name">div>          </template>          <!-- 區塊:self -->          <template v-if="item.userName == userName">            <div class="messageBox messageBox--self">              <div class="messageBox__time messageBox__time--self">{{item.timeStamp}}</div>              <div class="messageBox__content messageBox__content--self">                <div class="messageBox__text messageBox__text--self">{{item.message}}</div>              </div>            </div>          </template>        </template>      </div>      <!-- 區塊:bottom -->      <!-- 註解:使用:class來寫class是否顯示的判斷式{ class: 判斷式 } -->      <div class="roomBottom" :class="{ disable: !userName }">        <div class="roomBottom__tools"></div>        <div class="roomBottom__input">          <!-- 若要再帶入原生js的event(e)到function中,必須使用$event當參數傳入 -->          <textarea id="js-message" class="roomBottom__input__textarea"                    :class="{ disable: !userName }"                    @keydown.enter="sendMessage($event)"></textarea>        </div>      </div>    </div>    <!-- 區塊:modal -->    <div id="js-modal" class="modal">      <div class="modal__container">        <header class="modal__header">          <h2 class="view-title">輸入名稱</h2>        </header>        <div class="modal__body">          <!-- 註解:使用@keydown.enter來偵測keydown enter,觸發時執行method中的saveName() -->          <input type="text" id="js-userName" class="userName" maxlength="6" @keydown.enter.="saveName()">          <div class="button" @click="saveName()">設定</div>        </div>        <footer class="modal__footer"></footer>      </div>    </div>  </div></template>
    
    <script>// msgRef = firebase中的資料表/messages/,若沒有的會自動建立const msgRef = firebase.database().ref('/messages/');export default {  // 指定此頁使用的name  name: 'ChatRoom',  // 資料位置,於html中可用{{}}渲染出來  data() {    return {      userName: '',      messages: []    }  },  // 這個頁面的functions  methods: {    /** 彈出設定視窗 */    setName() {      document.querySelector('#js-modal').style.display = 'block';    },    /** 儲存設定名稱 */    saveName() {      // vue的mtthod中this是指export中這整塊的資料      const vm = this;      const userName = document.querySelector('#js-userName').value;      if (userName.trim() == '') { return; }      // 這裡的vm.userName(this.userName)就是data()裡面的userName      vm.userName = userName;      document.querySelector('#js-modal').style.display = 'none';    },    /** 取得時間 */    getTime() {      const now = new Date();      const hours = now.getHours();      const minutes = now.getMinutes();      const format = (hours >= 12) ? "下午" : "上午";      return `${format} ${hours}:${minutes}`;    },    /** 傳送訊息 */    sendMessage(e) {      const vm = this;      let userName = document.querySelector('#js-userName');      let message = document.querySelector('#js-message');      // 如果是按住shift則不傳送訊息(多行輸入)      if (e.shiftKey) {        return false;      }      // 如果輸入是空則不傳送訊息      if(message.value.length <=1 && message.value.trim() == '') {        // 避免enter產生的空白換行        e.preventDefault();        return false;      }      // 對firebase的db做push,db只能接受json物件格式,若要用陣列要先轉字串來存      msgRef.push({        userName: userName.value,        message: message.value,        // 取得時間,這裡的vm.getTime()就是method中的getTime        timeStamp: vm.getTime()      })      // 清空輸入欄位並避免enter產生的空白換行      message.value = '';      e.preventDefault();    }  },  // mounted是vue的生命週期之一,代表模板已編譯完成,已經取值準備渲染HTML畫面了  mounted() {    const vm = this;    msgRef.on('value', function(snapshot) {      const val = snapshot.val();      vm.messages = val;    })  },  // update是vue的生命週期之一,接再munted後方代表HTML元件渲染完成後  updated() {    // 當畫面渲染完成,把聊天視窗滾到最底部(讀取最新消息)    const roomBody = document.querySelector('#js-roomBody');    roomBody.scrollTop = roomBody.scrollHeight;  }}</script>
    
    <style scoped>/* CSS太多,不占版面放於github供參考 */</style>

執行與編譯

  1. 使用指令npm run dev來讓這專案在本機掛server起來(預設8080port),
    之後每次調整檔案內容,網頁就會自動刷新,非常方便開發及測試:D!
  2. 編譯使用npm run build會將src中所撰寫的資訊都壓縮至dist資料夾內。

    稍微備註,編譯後的index在載入js/css時的路徑有多一個.
    會導致放靜態主機時讀取錯誤(因為其實是在同一層),
    所以可以到config/index.js中將設定調整為assetsPublicPat = ''來解決

心得

目前還有卡著JS30尚未練習及寫完心得,
但看著各路大神分享的資源,就一直很想寫看看XD
vue-cli & firebase & webpack都是第一次使用,
這個練習後,對這三神器終於有很基礎的理解了。

vue.js

我最初會想學習vue是因為有中文文件(遮臉),
以及方便載入(可以直接掛載一個vue.js在html中來使用,像jQuery一樣),
目前這專案我學習到的是HTML中的template及v-if/v-for,
以及on(@),bind(:)的用法,很方便可以組織動態的前端邏輯,
而不用在js中組大量的字串模板。

在js控制中,我覺得生命周期的設定很棒,
可以很方便且”清楚”的在預想的狀況中設定應該出現的效果,
例如整個渲染完成前可以掛一個加載的效果等等..

但這小練習我都把邏輯整在同一個vue中,
還未學到/使用在vue中正確拆分邏輯的做法。

Firebase

之前有稍微聽過被google合併,但就僅此於而已此從未使用及了解過XD
這次練習中使用到的database覺得很新奇阿,是一個雲端即時同步的noSQL,
設定非常簡單方便,也是第一次親身寫出/感受到websoket的效果感(超酷)。
其他相關的功能也很多,之後有機會一定要在多研究一下(越來越多待讀項目..)

Webpack

一直有聽到,看過,但從未使用過,
但其實這次使用後的算是知道如何使用,但不了解內容,
對於設定檔目前沒有細讀,並不是很熟悉各相關設定檔,
反而覺得最特別的是熱加載及編譯後的程式碼壓縮混淆!
但日後練習都用webpack起,遇到問題找解答,應該會越來越熟吧XD

感謝

六角學院放出的Vue教學系列,從幼幼班入門到vue-cli & firebase介紹,
讓我能從零學習相關知識,從而建立完這個練習:)

六角學院在本週日也要釋放Bootstrap的課程了!
但不知何時才有空可以把全系列看過並實作完啊QQ….

六角學院-FB
洧杰老師-FB
卡斯伯老師-FB

原文地址:https://www.cnblogs.com/liuzhongrong/p/12257922.html

时间: 2024-08-02 12:09:04

用 Vue.js + Firebase 製作即時聊天功能的相关文章

Vue.js小Demo--单选和复选功能实现

Vue官方文档上有单选按钮radio和复选按钮checkbox的例子. 受此启发,写了这个小demo. 演示图: demo.vue文件代码: <div> <div class="Select"> <p class="Title">Single choice</p> <span class="Box" :class="{Selected_active:index == One}&quo

Vue.js先入个门看看

使用vue.js原文介绍:Vue.js是一个构建数据驱动的web界面库.Vue.js的目标是通过尽可能简单的API实现响应式数据绑定和组合的视图组件.vue.js上手非常简单,先看看几个例子: 例一:Helloworld html代码: <div id="app"> {{ message }} </div> js代码: new Vue({ el: '#app', data: { message: 'Hello Vue.js!' } }) 例二:双向绑定 说明:h

Vue.js中传值给子部件及触发动作的问题

最近研究一个用vue.js做的程序并修改增加功能.其中用到传值给子部件等问题. template中有个子部件: <template> ...... <child-form  v-if="flag=1" ></child-form> 要传值给它,方法是: 1. 本template中定义一个data: data() { return { flag:0, someId:"" } } 2. 子部件中定义一个props: props: [

【Vue】vue.js常用指令

http://www.cnblogs.com/rik28/p/6024425.html Vue.js的指令是以v-开头的,它们作用于HTML元素,指令提供了一些特殊的特性,将指令绑定在元素上时,指令会为绑定的目标元素添加一些特殊的行为,我们可以将指令看作特殊的HTML特性(attribute). Vue.js提供了一些常用的内置指令,接下来我们将介绍以下几个内置指令: v-if指令 v-show指令 v-else指令 v-for指令 v-bind指令 v-on指令

Vue.js 基础指令实例讲解(各种数据绑定、表单渲染大总结)——新手入门、高手进阶

Vue.js 是一套构建用户界面的渐进式框架.他自身不是一个全能框架--只聚焦于视图层.因此它非常容易学习,非常容易与其它库或已有项目整合.在与相关工具和支持库一起使用时,Vue.js 也能完美地驱动复杂的单页应用.他是基于AnjularJs 编写的,所以和前者的语法特别相似,却又使用简洁了很多. 那今天,我就给大家详细的说道说道这个 Vue.js ,以下是我们这次详解的目录,朋友们可以根据自己的情况选择性阅读,所有操作均附有代码实现. 1. Vue.js 如何绑定到页面中,使用他的功能. 2.

使用Vue.js制作仿Metronic高级表格(一)静态设计

Metronic高级表格是Metonic框架中自行实现的表格,其底层是Datatables,本教程将主要使用Vue实现交互部分,使用Bootstrap做样式库,jQuery做部分用户交互(弹窗). 使用到的库:Vue 2.0,Bootstrap3.jQuery2.font-awesome4,均可在CDN下载 需要注意的是,Vue最好使用开发版本 一.需求和原型设计 产品目标是一个图书管理表格,书籍字段:书籍名称.分类.价格.更新时间. 需求: ① 书籍信息的增删改 ② 分页功能,并且能自行选择

Vue.js——60分钟快速入门

Vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和组件化的思想构建的.相比于Angular.js,Vue.js提供了更加简洁.更易于理解的API,使得我们能够快速地上手并使用Vue.js. 本文摘自:http://www.cnblogs.com/keepfool/p/5619070.html 如果你之前已经习惯了用jQuery操作DOM,学习Vue.js时请先抛开手动操作DOM的思维,因为Vue.js是数据驱动的,你无需手动操作DOM.它通过一些特殊的HTML语法,将

Vue.js——快速入门

Vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和组件化的思想构建的.相比于Angular.js,Vue.js提供了更加简洁.更易于理解的API,使得我们能够快速地上手并使用Vue.js. 本文摘自:http://www.cnblogs.com/keepfool/p/5619070.html 如果你之前已经习惯了用jQuery操作DOM,学习Vue.js时请先抛开手动操作DOM的思维,因为Vue.js是数据驱动的,你无需手动操作DOM.它通过一些特殊的HTML语法,将

Vue.js——60分钟组件快速入门(上篇)

组件简介 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小组件来构建大型应用,任意类型的应用界面都可以抽象为一个组件树: 那么什么是组件呢?组件可以扩展HTML元素,封装可重用的HTML代码,我们可以将组件看作自定义的HTML元素. 本文的Demo和源代码已放到GitHub,如果您觉得本篇内容不错,请点个赞,或在GitHub上加个星星!(所有示例都放在GitHub Pages上了,请访问https://github.com/keepfool/vue-tut