【问题标题】:Websockets in Vue/Vuex (how to receive emissions from server)Vue/Vuex 中的 Websockets(如何从服务器接收发射)
【发布时间】:2020-05-15 12:25:39
【问题描述】:

所以直到现在我只是 socket.io-client 与我的 Vue 组件中的 WebSocket 进行通信。 现在我正在将 Vuex 添加到项目中并声明一个这样的 Websocket

Vue.use(new VueSocketIO({
  debug: true,
  connection: 'http://192.168.0.38:5000',
}));

new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount('#app');

1) 我现在应该在组件本身还是在商店中发送一些消息之类的东西?

2) 在我介绍这些更改之前,我可以这样做:

socket.on('connect', function () {
      console.error('connected to webSocket');
      socket.emit('my event', { data: 'I\'m connected!' });
    });

socket.on('my response', function(data){
      console.log('got response');
      console.log(data.data);
    });

当发送“我的事件”时,烧瓶服务器会响应“我的响应”。现在,在进行了这样的更改之后,我正在尝试从组件中进行相同的操作。

    this.$socket.emit('my_event', { data: 'I\'m connected!' });
    console.error('send to websocket ');

    this.$options.sockets.my_event = (data) => {
      console.error('received answer ');
      console.error(data);
    };

my_event 到达了我的烧瓶服务器,但是我没有收到接收到的响应。我究竟做错了什么? 另外因为我在问我应该把它放在组件还是商店中,我为商店找到了这样的东西:

SOCKET_MESSAGECHANNEL(state, message) {
      state.socketMessage = message
    }

解释是“因此,例如,如果您的频道称为 messageChannel,则相应的 Vuex 突变将是 SOCKET_MESSAGECHANNEL”,它来自此站点 https://alligator.io/vuejs/vue-socketio/

我想我现在并没有真正了解频道是什么。我从烧瓶服务器发出的 my_response 也是一个通道吗? 提前感谢您的帮助!

编辑:所以现在我正在尝试从我的商店监听并发送到 websocket。为此,我尝试了以下方法:在 main.js 我有这部分:

Vue.use(new VueSocketIO({
  debug: true,
  connection: SocketIO('http://192.168.0.38:5000'),
  vuex: {
    store,
    actionPrefix: 'SOCKET_',
    mutationPrefix: 'SOCKET_',
  },
}));

然后在我的 store.js 中有以下内容:

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    count: 0,
    title: 'title from vuex store',
    isConnected: false,
  },
  mutations: {
    increment(state) {
      state.count += 1;
    },
    emitSth(state) {
      this.sockets.emit('my_event', { data: 'I\'m connected!' });
      console.log(state.count);
    },
    SOCKET_my_response(state) {
      state.isConnected = true;
      alert(state.isConnected);
    },
    SOCKET_connect(state) {
      state.isConnected = true;
      alert(state.isConnected);
    },
  },
});

在我的组件中,我有这个脚本:

export default {
  name: 'ControlCenter',
  data() {
    return {
      devices: [{ ip: 'yet unknown' }], // placeholder so line 12 does not throw error before actual device info fetched
      thisDeviceIndex: 0,
      currentLayoutIndex: 0,
      layouts: [],
    };
  },
  computed: mapState([
    'title',
    'count',
  ]),
  components: {
    DNDAssign,
    FirstPage,
  },
  methods: {
    // mapMutation helper let's us use mutation from store via this instead of this.$store
    ...mapMutations([
      'increment',
      'emitSth',
    ]),
    incrementMutation() {
      this.increment();
    },
    emitEvent() {
      this.emitSth();
    },
    // some other stuff here
  },
  created() {
    // inital fetching of layouts
    console.log('fetching layouts from backend');
    this.getAllLayouts();

    console.log(this.$socket);
  },
};

我还有一个用于触发发射的按钮

<b-button
type="button"
variant="success"
v-on:click="emitEvent()"
>
emit event
</b-button>

商店中的连接被触发,但是我收到以下发射错误

  • “TypeError:无法读取未定义的属性‘emit’”
  • “无法读取未定义的属性 'emit'”

我也不确定突变中的命名。如果我有这个 mutationPrefix,难道只使用 connect 而不是 SOCKET_connect 就足够了吗?

【问题讨论】:

  • 不,前缀是用来区分普通动作和套接字动作的,所以如果你有SOCKET_作为前缀,并且在服务器上你发出someMessage,它会调用带有名称的vuex动作SOCKET_someMessage

标签: javascript vue.js socket.io vuex


【解决方案1】:

首先,如果你使用的是Vue-Socket.io 3.0.5版本>,卸载它并安装3.0.5版本

npm uninstall vue-socket.io
npm install vue-socket.io@3.0.5

然后将版本锁定在packege.json:"vue-socket.io": "3.0.5",最新更新似乎破坏了库,阅读更多here

现在要从 socket.io 服务器接收事件,你可以这样做:

this.sockets.subscribe("my response", (data) => {
    console.log(data);
});

或者如果要将监听器放在组件级别,则需要在组件导出上添加sockets对象,例如:

export default {
    ...
    sockets: {
        "my response": function (data) {
            console.log(data);
        }
    }
    ...
}

由于您没有在 VueSocketIO 上使用 Vuex 集成,因此您不需要在存储突变中添加额外的功能。如果想在 VueSocketIO 上使用 Vuex 集成,需要在声明 VueSocketIO 类时添加vuex 对象。

这是main.js的基本示例

// Set Vue to use Vuex
Vue.use(Vuex);

// Create store
const store = new Vuex.Store({
  state: {
      someData: null
  },
  getters: {},
  actions: {
      "SOCKET_my response"(context, data) {
          // Received `my response`, do something with the data, in this case we are going to call mutation "setData"
        context.commit("setData", data);
      }
  }
  mutations: {
      ["setData"](state, data) {
          state.someData = data; // Set it to state
      }
  }
});

// Set Vue to use VueSocketIO with Vuex integration
Vue.use(new VueSocketIO({
  debug: true,
  connection: 'http://192.168.0.38:5000',
  vuex: {
      store,
      actionPrefix: "SOCKET_"
    }
}));

new Vue({
  router,
  store
  render: h => h(App)
}).$mount("#app");

如果您需要有关 Vuex 集成的示例,您可以查看使用 Vue 和 Vue-Socket.io 与 Vuex 集成的my example app。te

【讨论】:

  • 非常感谢 Owl 的广泛回答!我尝试了不同的方法,你建议。我现在唯一想知道的是,何时使用这些选项中的哪一个。是不是例如只是个人喜好,如果我像在第一个 sn-p 中那样做还是在组件级别上做呢?或者有什么理由什么时候把它放在哪里?还有在哪些情况下将其添加到 vuex 存储中有意义?
  • 我认为这取决于事件的用途以及您的 Vue 应用程序的结构,例如,如果您正在构建一个聊天应用程序,并且您有自己的聊天视图 (Chat.vue) ,然后我会使用组件级侦听器。首先 sn-p 是动态侦听器,这意味着您可以 .subscribe 和 .unsubscribe 开始和停止侦听事件,除非您需要执行 .unsubscribe ,否则我个人不会使用它,因为 Component 级别看起来更清晰和结构化我。并且仅当您使用 Vuex 存储来存储您的数据(例如聊天列表)时才使用 Vuex 集成,这样您就可以更轻松地改变您的数据。
  • 啊,这绝对有道理,再次感谢您抽出宝贵的时间!我认为由于在我的应用程序中我想从 websocket 获取一些数据并且这些数据应该在多个组件中使用,所以 vuex 存储解决方案可能是最好的。我查看了文档和您的代码,但不幸的是,我仍然不知道如何为 my_response 编写东西,或者也只是连接到 vuex 商店。我会将我尝试过的细节添加到我原来的问题中,并很高兴获得进一步的帮助
  • 我刚收到消息“感谢您提交编辑。只有在得到受信任的社区成员批准后,您才能看到它”,所以我希望其他人能看到它真的觉得被这个困住了
  • 更新了我的答案以帮助您入门。
猜你喜欢
  • 2019-12-18
  • 2019-04-13
  • 2023-02-11
  • 1970-01-01
  • 1970-01-01
  • 2019-06-02
  • 2013-08-17
  • 2011-02-27
  • 2010-12-19
相关资源
最近更新 更多