WEB實例:開發一個聊天室應用

前言

這篇文章介紹如何使用 Vue.js 以及 chatkit 快速的開發一個聊天室應用,chatkit 提供了一系列 api 用以更方便的開發聊天功能,源碼地址.css

建立Chatkit實例

首先須要創建一個 Chatkit 實例, 前往 chatkit控制檯 創建,建好以後新建一個房間以及用戶,將以後要用到的 instanceLocator, key 記錄到本地html

創建後端服務

新建一個 Node.js 服務用來建立用戶以及提供 jwt token,安裝依賴 yarn add express cors pusher-chatkit-server 啓動服務。前端

const cors = require('cors')
const express = require('express')
const Chatkit = require('pusher-chatkit-server')
const config = require('../config')

const app = express()
const PORT = config.SERVER_PORT || 4399

app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: false }))

// eslint-disable-next-line
const chatkit = new Chatkit.default({
  instanceLocator: config.CHATKIT_INSTANCELOCATOR,
  key: config.CHATKIT_KEY
})

app.post('/user', (req, res) => {
  const { username } = req.body

  const user = {
    id: username,
    name: username
  }

  chatkit
    .createUser(user)
    .then(() => res.status(201).json({ success: true, message: '建立用戶成功', user }))
    .catch(error => {
      res.status(error.status).json({ success: false, message: error.error_description })
    })
})

app.post('/auth', (req, res) => {
  const data = chatkit.authenticate({ userId: req.query.user_id })
  res.status(data.status).json(data.body)
})

app.listen(PORT, error => {
  if (error) {
    console.log(error)
  } else {
    console.log(`Server running on port ${PORT}`)
  }
})

複製代碼

新建前端項目

新建一個 Vue.js 項目,創建一個用來建立新用戶的表單, 表單提交到剛纔建立的 express 服務的 user 路由vue

<form class="create__form" @submit.prevent="createUser">
  <input class="create__input" v-model="newUserName" placeholder="輸入你的名字" autofocus required /> </form>
複製代碼
async createUser() {
  const username = this.newUserName

  const result = await fetch(`${config.SERVER_HOST}:${config.SERVER_PORT}/user`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ username })
  })
  .then(res => res.json())
  .catch(error => error)

  if (result.success) {
    const user = result.user
    this.initChatApp(user.name) // 建立用戶成功
  } else {
    console.log(result)
  }
}
複製代碼

新建用戶成功後,初始化應用react

async initChatApp(userId) {
  const chatManager = new Chatkit.ChatManager({
    userId,                                           // 用戶名稱
    instanceLocator: config.CHATKIT_INSTANCELOCATOR,  // instanceLocator
    tokenProvider: new Chatkit.TokenProvider({       
      url: `${config.SERVER_HOST}:${config.SERVER_PORT}/auth`
    })
  })

  const currentUser = await chatManager.connect()

  const currentRoom = await currentUser
    .joinRoom({
      roomId: config.CHATKIT_ROOM_ID
    })
    .catch(error => {
      return error
    })
    
  currentUser.subscribeToRoom({
    messageLimit: 20,
    roomId: config.CHATKIT_ROOM_ID, // 在控制檯創建的房間ID
    hooks: {
      onNewMessage: message => {
        this.users = this.users.map(user => {
              if (user.name === message.senderId) {
                user.online = true
              }
              return user
            })
            this.messages.push(message)
          }
        }
    })

  const messages = await currentUser
    .fetchMessages({
      roomId: config.CHATKIT_ROOM_ID,
      direction: 'older',
      limit: 20
    })
    .catch(error => {
        console.error(error)
    })

  this.currentUser = currentUser
  this.currentRoom = currentRoom
  this.users = currentRoom.userIds.filter(name => name !== currentUser.name).map(name => {
    return { name, online: false }
  })
  this.messages = messages
}
複製代碼

頁面佈局

進行佈局以及UI,使用 Grid 進行快速佈局, 創建用戶列表,消息列表以及發送消息的表單git

<ul class="chat__users">
  <li class="user-item" v-for="user of users" :key="user.id">
   <span class="name">{{ user.name }}</span>
   <span class="spot" :class="{ 'spot--online': user.online }"></span>
  </li>
</ul>
複製代碼
<ul class="chat__messages">
  <message-item v-for="(message, index) of messages" :key="index" :message="message" :currentUser="currentUser" />
</ul>
複製代碼
<form class="chat__send" @submit.prevent="sendMessage">
  <input class="input" type="text" @change="typingMessage" v-model="newMessage" autofocus required placeholder="說點什麼..." />
  <button class="button" type="submit">發送</button>
</form>
複製代碼
.chat {
  display: grid;
  grid-auto-columns: 240px auto;
  grid-auto-rows: 30px auto 70px;
  grid-template-areas:
    'users messages'
    'users messages'
    'users send';
  height: 100vh;
}  
複製代碼

發送消息

使用 chatkit 提供的api便可github

sendMessage() {
  this.currentUser // 當前用戶
    .sendMessage({
      text: this.newMessage, // 消息內容
      roomId: config.CHATKIT_ROOM_ID // 房間ID
    })
    .then(messageId => {
      this.newMessage = ''
    })
    .catch(error => {
      this.newMessage = ''
       console.log(error)
    })
}
複製代碼

最後

開發完成後,使用 yarn build 命令將 Vue 項目打包,而後使用 express 內置的 static 中間件掛載打包後的 dist 目錄, 在瀏覽器中打開 express 運行的端口就能夠看到效果了,文章只是簡述如何開發,具體實現請看 github 源碼。express

app.use('/', express.static(path.join(__dirname, '/dist')))
複製代碼

參考

vue-chatjson

CHATKIT DOCS後端

Build a Slack Clone with React and Pusher Chatkit

相關文章
相關標籤/搜索