Задать вопрос
@Viktimius
js developer

Как организовать работу стора и сокета в рамках одного приложения?

Доброго времени суток,

кратко о проекте: мессенджер на nuxt (ui - vuetify), vue-socket.io. Как уже понятно - не каждый день пишу мессенджеры.

Проблема

В мессенджере настроена обработка эвентов от сокета, прием и отправка сообщений, но не получается записать в объект стора сообщения - не отрабатывает мутация, хотя если обращаться к стору через this.$store.state.messages - запись происходит, но она не отслеживается nuxt. Вопрос как организовать стандартную обработку и хранение сообщений в сторе (actions, mutations, getters) ?! Звучит банально - но решения не нашел. Буду рад если подскажите куда копать или поделитесь примерами, ссылками на статьи.....


Вопрос про гугл и баны
Не забанен ! Но решение не нашел.


Код для подклчения сокета

import Vue from 'vue';
import VueSocketIO from 'vue-socket.io';

export default function({store}) {
  Vue.use(new VueSocketIO({
    debug: true,
    connection: '********',
    vuex: {
        store,
        actionPrefix: 'SOCKET_',
        mutationPrefix: 'SOCKET_'
    },
  }))
}



Код компонента отправки сообщений

<template>
  <v-container fluid style='padding: 0;'>
    <v-row no-gutters>
      <v-col sm='12' style='position: relative;'>
        <div>
          <ChatWindow />
        </div>
        <div class='typer'>
          <input type='text' placeholder='Введите сообщение...' v-on:keyup.enter='sendMessage' v-model='message' />
          <v-btn icon class='blue--text emoji-panel'>
            <v-icon>mdi-emoticon-outline</v-icon>
          </v-btn>
        </div>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
import ChatWindow from '@/components/Chat/ChatWindow.vue';

export default {
  components: {
    ChatWindow,
  },
  data () {
    return {
      message: '',
      emojiPanel: false,
      currentRef: {},
      loading: false,
      totalChatHeight: 0,
      id: this.$route.params.id,
    }
  },
  methods: {
    sendMessage() { 
      this.$socket.emit( // эвент сокета, отправка сообщения
        'send_msg',
        {
          dialog_id: this.id,
          msg: this.message,
        }
      )

      this.$store.commit('updateMessageBySocket', {
        dialog_id: this.id,
        action: 'send_msg',
        message: this.message,
      });

      this.message = '';
    },
  },
}
</script>



Код компонента окна(отображение диалога между пользователями)

<template>
  <v-container class='chat-window'>
    <v-container class='chat-container' @scroll='onScroll' >
      <div class='d-flex message' v-for="(message,index) in messages" :key="index">
        <v-container v-if='message.action === "send_msg"' class="message__wrap d-flex justify-end">
          <div class='d-flex flex-column justify-end col-5 message__box teal'>
            <div class="d-flex justify-space-between message__data-box">
              <div class='message__user'>Admin</div>
              <div class="message__date">{{ convertDate(message.created_at) }}</div>
            </div>
            <div class="d-flex justify-end message__content-box">
              <div class='content'>
                {{ message.message }}
              </div>
            </div>
          </div>
        </v-container>
        <v-container v-else-if='message.action === "receive_msg"' class="message__wrap d-flex justify-start">
          <div class='d-flex flex-column justify-start col-5 message__box blue'>
            <div class="d-flex justify-space-between message__data-box">
              <div class='message__user'>{{ `${dialog.user.first_name} ${dialog.user.last_name} ${dialog.user.username}` }}</div>
              <div class="message__date">{{ convertDate(message.created_at) }}</div>
            </div>
            <div class="d-flex justify-start message__content-box">
              <div class='content'>
                {{ message.message }}
              </div>
            </div>
          </div>
        </v-container>
      </div>
    </v-container>
  </v-container>
</template>

<script>
import { mapState, mapActions, mapGetters, mapMutations } from 'vuex';

export default {
  data () {
    return {
      id: this.$route.params.id,
    };
  },
  mounted() {
    this.fetchDialogByID(this.id); // информация по диалогу, кто с кем общается, когда начат диалог и т.д.(объект)
    this.fetchMessagesForDialogByID(this.id); // список сообщений(массив)
  },
  computed: {
    dialog() {
      return this.getCurrentDialog();
    },
    messages() {
      return this.$store.state.messages[this.id];
    }
  },
  methods: {
     .......
  },
}
</script>



Стор

export const actions = {
....
SOCKET_receive_msg({ commit }, data) { // эвент сокета - получение сообщения
    const message = {
      dialog_id: data.dialog_id,
      action: 'receive_msg',
      message: data.msg,
      created_at: data.timestamp,
      not_read: !!data.unread,
    };

    console.log(message);
    commit('updateMessageBySocket', message);
  }

export const mutations = {
    updateMessageBySocket(state, payload) {
           // мутация изменения стора не срабатывает
           // пробовал разные варианты 
           // state.messages[payload.dialog_id].push(payload);   - вариант 1 
          //  const index = state.messages[state.dialog.id].length;   - вариант 2
          //  this._vm.$set(state.messages[state.dialog.id], index, payload); - вариант 2
  },
}

  • Вопрос задан
  • 113 просмотров
Подписаться 1 Простой Комментировать
Решения вопроса 1
@frankieksai
Возможно проблема в реактивности VUE?

В вашем очень подробном описании ключевой код мутации и не приведён.
Если у вас там простое присваивание, типа
state.message = payload
то попробуйте заменить это на следующую строку
Vue.set(state, 'message', payload)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы