Vue Academy · レッスン

リアルタイムチャットコンポーネントの構築

v-forによるメッセージ一覧、入力バインディング、送信時のemit、新着メッセージ時の最下部へのスクロール

レッスン 3/413 ステップ

「リアルタイムチャットコンポーネントの構築」はCoddyKit上の無料Vue Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはVue Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Vue Academyコースには全4レッスンが含まれています。

目標:リアルタイムチャットボックス

小さいながらも完全なチャットコンポーネントを組み立てます。スクロール可能なメッセージ一覧を表示し、ユーザーが入力して送信できるようにし、受信したメッセージをリアルタイムで追加します。

ここでは、リアクティブな状態、ライフサイクルフック、DOM へのアクセスを組み合わせます。

メッセージの ref

会話をリアクティブな配列に保持します。各項目は、id、author、text を持つ単純なオブジェクトです。

import { ref } from "vue"

const messages = ref([
  { id: 1, user: "system", text: "Welcome to the room" },
])

入力用の ref

v-modelを使って、テキストボックスを別の ref にバインドします。送信前に作成中のメッセージを保持するための ref です。

// template:
// <input v-model="draft" @keyup.enter="sendMessage" />

const draft = ref("")

ソケットリスナーを登録する

onMounted内で受信メッセージを購読し、それぞれを配列に追加します。onMountedを使うと、ハンドラーをアタッチする前にコンポーネントの準備が完了していることが保証されます。

import { onMounted } from "vue"

onMounted(() => {
  socket.on("message", (msg) => {
    messages.value.push(msg)
  })
})

メッセージを送信する

sendMessage関数は下書きをサーバーに送信し、入力欄をクリアします。空文字列を送信しないようにチェックします。

function sendMessage() {
  const text = draft.value.trim()
  if (!text) return
  socket.emit("send", { text })
  draft.value = ""
}

一覧を表示する

テンプレートでv-forを使ってmessagesを id でキー付けしてループします。各行には author と text を表示します。

<!-- template -->
<div ref="chatBox" class="chat">
  <p v-for="m in messages" :key="m.id">
    <strong>{{ m.user }}:</strong> {{ m.text }}
  </p>
</div>

スクロールの問題

新しいメッセージが届くと、ユーザーは表示位置が最下部に固定されることを期待します。しかし、配列に追加した直後にスクロールしても、新しい行はまだ DOM に存在しません。Vue が更新を反映していないためです。

スクロールのタイミングが早すぎるため、最新の行を見逃してしまいます。

コンテナへのテンプレート ref

テンプレート ref を使ってスクロールコンテナを取得し、スクロール位置を読み取ったり設定したりできるようにします。

import { ref } from "vue"

const chatBox = ref(null)

// template: <div ref="chatBox"> ... </div>

nextTickでDOMを待機する

nextTickは、Vueが保留中のDOM更新を適用した後に解決されるpromiseを返します。新しいメッセージがDOMに存在するよう、スクロールする前にawaitしてください。

import { nextTick } from "vue"

async function scrollToBottom() {
  await nextTick()
  const el = chatBox.value
  el.scrollTop = el.scrollHeight
}

新しいメッセージごとにスクロールする

メッセージを追加した直後にscrollToBottomを呼び出してください。受信メッセージと送信メッセージの両方で必要です。scrollTop = scrollHeightを設定すると、一番下まで移動します。

onMounted(() => {
  socket.on("message", async (msg) => {
    messages.value.push(msg)
    await scrollToBottom()
  })
})

完成したフロー

これでコンポーネントは、メッセージを受信し、リアクティブな状態を更新し、nextTickでDOMの更新を待ってからスクロールするようになりました。送信時も同じ流れになります。シンプルで予測しやすい、リアルタイムな処理です。

async function sendMessage() {
  const text = draft.value.trim()
  if (!text) return
  socket.emit("send", { text })
  draft.value = ""
  await scrollToBottom()
}

クイックチェック

チャットコンポーネントにおけるDOMのタイミングについて、理解度を確認してください。

まとめ

このレッスンでは、リアルタイムチャットコンポーネントを構築しました。重要なポイントは次のとおりです。

  • メッセージをリアクティブなref配列で管理し、入力途中の内容は独自のrefで管理します。
  • onMountedでソケットのリスナーを登録し、受信したメッセージを追加します。
  • sendMessageで入力途中の内容を送信し、入力欄をクリアします。
  • テンプレートrefとawait nextTick()を使い、scrollTop = scrollHeightを設定する前にDOMの更新を待って、最新のメッセージが表示されるようにします。
無料で開始

AI チューターと学ぶ HTML — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
42
レッスン
156

よくある質問

「リアルタイムチャットコンポーネントの構築」レッスンは無料ですか?

はい。「リアルタイムチャットコンポーネントの構築」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Vue Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Vue Academyコースには全4レッスンが含まれています。

「リアルタイムチャットコンポーネントの構築」で何を学びますか?

v-forによるメッセージ一覧、入力バインディング、送信時のemit、新着メッセージ時の最下部へのスクロール ブラウザで直接実行するハンズオンコードでVue Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Vue Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのVue Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「リアルタイムチャットコンポーネントの構築」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このVue Academyレッスンでコードを書いて実行できますか?

はい。すべてのVue Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ブラウザでのWebSocket入門
  2. VueでのSocket.ioクライアント
  3. リアルタイムチャットコンポーネントの構築
  4. 再接続対応useWebSocket Composable
← Vue Academyに戻る