Vue Academy · Урок

Создание компонента чата в реальном времени

Список сообщений с v-for, привязка ввода, отправка события при подтверждении и прокрутка вниз при новом сообщении

Урок 3 из 413 шагов

«Создание компонента чата в реальном времени» — бесплатный урок Vue Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Vue Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Vue Academy содержит 4 уроков всего.

Цель: окно чата в реальном времени

Мы соберём небольшой, но полноценный компонент чата: он отображает прокручиваемый список сообщений, позволяет пользователю вводить и отправлять сообщения, а также добавляет входящие сообщения в реальном времени.

В этом примере объединяются реактивное состояние, хуки жизненного цикла и доступ к DOM.

Ссылка на сообщения

Храните переписку в реактивном массиве. Каждая запись представляет собой простой объект с идентификатором, автором и текстом.

import { ref } from "vue"

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

Ссылка для поля ввода

Свяжите текстовое поле с отдельной ссылкой с помощью v-model. В ней хранится составляемое сообщение до его отправки.

// 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 = ""
}

Отображение списка

Шаблон перебирает messages с помощью v-for, используя идентификатор в качестве ключа. В каждой строке отображаются автор и текст.

<!-- 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 ещё не применил обновление.

Прокрутка происходит слишком рано, и последняя строка остаётся за пределами видимой области.

Ссылка на контейнер в шаблоне

Получите контейнер прокрутки через ссылку шаблона, чтобы читать и задавать его положение прокрутки.

import { ref } from "vue"

const chatBox = ref(null)

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

Ожидание DOM с помощью nextTick

nextTick возвращает промис, который выполняется после того, как Vue применит ожидающие обновления DOM. Дождитесь его выполнения перед прокруткой, чтобы новое сообщение появилось в DOM.

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()
  })
})

Полный процесс

Теперь компонент получает сообщение, обновляет реактивное состояние, дожидается обновления DOM с помощью nextTick, а затем прокручивает содержимое. Отправка проходит по тому же пути. Чисто, предсказуемо, в реальном времени.

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

Быстрая проверка

Проверьте, насколько хорошо Вы понимаете синхронизацию с DOM в компоненте чата.

Итоги

В этом уроке Вы создали компонент чата, работающий в реальном времени. Главное:

  • Храните сообщения в реактивном массиве ref, а черновик — в отдельном ref.
  • Регистрируйте обработчик сокета в onMounted и добавляйте входящие сообщения.
  • sendMessage отправляет черновик и очищает поле ввода.
  • Используйте ссылку на элемент шаблона и await nextTick() перед установкой scrollTop = scrollHeight, чтобы было видно последнее сообщение.
Можно начать бесплатно

Изучай HTML с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
42
Уроки
156

Часто задаваемые вопросы

Урок «Создание компонента чата в реальном времени» бесплатный?

Да — полный текст урока «Создание компонента чата в реальном времени» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Vue Academy, подпишись на CoddyKit PRO. Курс Vue Academy содержит 4 уроков всего.

Чему я научусь в уроке «Создание компонента чата в реальном времени»?

Список сообщений с v-for, привязка ввода, отправка события при подтверждении и прокрутка вниз при новом сообщении Ты практикуешь Vue Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Vue Academy?

Предыдущий опыт не требуется. Vue Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Создание компонента чата в реальном времени»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Vue Academy?

Да. Каждый урок Vue Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Основы WebSocket в браузере
  2. Клиент Socket.io с Vue
  3. Создание компонента чата в реальном времени
  4. Композируемый модуль useWebSocket с переподключением
← Назад к Vue Academy