2017-10-10 2566 views
0

我想贡献一个项目 - 它是用Vue编写的,我是Vue的初学者。vue:从websocket监听器发出全局事件

我有两个组成部分 - SetupMainApp

双方将根据需要从WebSocket的不同消息更新一些状态。一些websocket消息会影响前者,一些会影响后者。

Vue不知道服务,所以我想我只是创建一个自定义组件,空<template>。在那里实例化websocket,然后每次在侦听器中发生新消息时发出一个this.emit()

这两个其他组件会听取发​​射,并将能够作出反应。我不能让websocket组件工作。

main.js:

import Ws from './WsService.vue'; 
//other imports 

const routes = [ 
    //routes 
] 


const router = new VueRouter({ 
    routes // short for `routes: routes` 
}) 

const app = new Vue({ 
    router 
}).$mount('#app') 
//I thought this to be the way to instantiate my webSocket service: 
const WsService = new Vue({ 
    el: '#WsService', 
    components: { Ws } 
}); 

的index.html

<body> 
    <div id="app"> 
     <div id="WsService"></div> 
     <router-link to="/setup">Setup</router-link> 
     <router-link to="/main-app">Main App</router-link> 
     <router-view></router-view> 
    </div> 
    <script src="/dist/demo-app.js"></script> 
    </body> 

WebSocket的 “服务”:

<template> 
</template> 

<script> 
const PORT_LOCAL = 9988; 
var ws = new WebSocket("ws://localhost:" + PORT_LOCAL); 
ws.onopen = function() { 
    ws.send('{"jsonrpc":"2.0","id":"reg","method":"reg","params":null}'); 
}; 

ws.onerror = function(e) { 
     console.log("error in WebSocket connection!"); 
     console.log(e); 
}; 

export default { 

    data() { 
    return { 
    } 
    }, 

    created() { 
    var self = this; 
    ws.onmessage = function(m) { 
      var msg = JSON.parse(m.data); 
      switch(msg.id) { 
      // result for address request 
      case "reg": 
       self.$emit("reg_received", msg.result); 
       break; 
      case "send": 
       self.$emit("send_received", msg.result); 
       break; 
      case "subscribe": 
       self.$emit("subscribe_received", msg.result); 
       break; 
      default: 
       console.log(msg); 
       break; 
      } 
    } 
    }, 

    methods: { 
    }, 

    send(id, method, params) { 
    ws.send('{"jsonrpc":"2.0","id":"' + id + '","method":"' + method + '","params":null}'); 

    } 
    } 

} 
</script> 

发送例如从主应用程序(这似乎工作) :

import WsSvc from './WsService.vue'; 
export default { 
    data() { 
    // 
    }, 
    subscribe() { 
    let jsonrpc = "the jsonrpc string"; 
    WsSvc.send(jsonrpc); 
    } 
} 

emit

export default { 
    data() { 
    // 
    }, 
    created() { 
    this.$on("reg_received", function(result){ 
     //do smth with the result 
    }); 

    } 
} 

威特此配置中,created钩实际上不会被调用 - 因此我永远不会打onmessage听众。我认为有一个自定义组件的原因是我可以访问emit函数。

感觉我让它变得比它应该更复杂,但我还没有设法让它正确。该解决方案不需要遵循这种方法。

+0

“Vue公司不知道服务”。这是不正确的。只需构建您的API并将其导入您想要使用它的组件。这里不需要组件。 – Bert

+0

@Bert也许你是对的,但问题不在于如何从onmessage回调并更新其他组件的属性。 – faboolous

+1

这个怎么样? https://codesandbox.io/s/4wp90vvr2w – Bert

回答

1

在这种情况下,不需要特定套接字组件。我在过去的几个项目中所做的是实现处理套接字消息的API或存储对象,然后将该API导入或存储到需要它的组件中。另外in a similar answer,我展示了如何整合一个WebSocket与Vuex。

下面是一个例子,它将使用Vue作为事件发射器的概念与可以导入任何组件的Web套接字相结合。该组件可以订阅并收听它想要收听的消息。以这种方式包装套接字将原始套接字接口抽象出来,并允许用户以更典型的Vue方式使用$ on/$ off订阅。

Socket.js

import Vue from "vue" 

const socket = new WebSocket("wss://echo.websocket.org") 

const emitter = new Vue({ 
    methods:{ 
    send(message){ 
     if (1 === socket.readyState) 
     socket.send(message) 
    } 
    } 
}) 

socket.onmessage = function(msg){ 
    emitter.$emit("message", msg.data) 
} 
socket.onerror = function(err){ 
    emitter.$emit("error", err) 
} 


export default emitter 

以下是在一个组件正在使用的代码的一个例子。

App。VUE

<template> 
    <ul> 
    <li v-for="message in messages"> 
     {{message}} 
     </li> 
    </ul> 
</template> 

<script> 
    import Socket from "./socket" 

    export default { 
     name: 'app', 
     data(){ 
      return { 
       messages: [] 
      } 
     }, 
     methods:{ 
      handleMessage(msg){ 
      this.messages.push(msg) 
      } 
     }, 
     created(){ 
      Socket.$on("message", this.handleMessage) 
     }, 
     beforeDestroy(){ 
      Socket.$off("message", this.handleMessage) 
     } 
    } 
</script> 

这里是一个working example

0

嘿,这应该为你工作好,容易

这是我的例子与.vue文件

yourVueFile.Vue

<template> 
// key in your template here 
</template> 

<script> 
export default { 
//use the created() option to execute after vue instance is created 
    created() { 
    let ws = new WebSocket("yourUrl"); 
    ws.onopen = e => { 
     ws.send(
     JSON.stringify({ your json code }) 
    ); 

     ws.onmessage = e => { 
     let data = JSON.parse(e.data); 

// the this.$data get your data() options in your vue instance 
      this.$data.dom = data; 

     }; 
    }; 
    }, 
    data() { 
    return { 
     dom: core 
    }; 
    }, 
    methods: { 

    } 
}; 
</script>