欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue使用?vue-socket.io三種方式及踩坑實(shí)例解析

 更新時(shí)間:2022年09月22日 09:12:29   作者:u、轉(zhuǎn)角  
這篇文章主要為大家介紹了vue使用?vue-socket.io三種方式及踩坑實(shí)例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

vue項(xiàng)目實(shí)時(shí)通信實(shí)現(xiàn)常用方式:

一、原生HTML5 WebSocket實(shí)現(xiàn),vue中使用websocket

二、插件socket.io官網(wǎng) ,Socket.io是一個(gè)WebSocket庫,包括了客戶端js和服務(wù)器端的nodejs,會自動根據(jù)瀏覽器從WebSocket、AJAX長輪詢、Iframe流等等各種方式中選擇最佳的方式來實(shí)現(xiàn)網(wǎng)絡(luò)實(shí)時(shí)應(yīng)用,最低支持IE5.5; 說白了就是如果瀏覽器支持websocket,那么socket.io就等同于websocket。當(dāng)然 socket.io還用到了其它的技術(shù)來模擬websocket,所以當(dāng)你使用socket.io的時(shí)候,不管瀏覽器是否支持websocket,你都可以實(shí)現(xiàn)異步操作。

使用注意:客戶端使用了socket.io 服務(wù)端也必須對應(yīng)使用

三、vue-socket.io是vue對socket.io的封裝,使用方式與socket.io大同小異,核心參數(shù)還是要參照socket.io官網(wǎng)相關(guān)配置;當(dāng)前在使用中也存在部分坑

當(dāng)前文章主要說vue-socket.io以下問題:

  • 初始化全局掛載使用,事件訂閱與銷毀(基本無坑,需注意訂閱事件要對應(yīng)銷毀,否則存在多次訂閱引發(fā)的消息重復(fù)接收問題)
  • 帶token驗(yàn)證的全局掛載方式(有坑,有解決方案與解決后使用注意事項(xiàng))
  • 組件內(nèi)使用

安裝

建議直接使用taobao鏡像,淘寶鏡像地址建議使用新地址,老地域名將于2022年05月31日零時(shí)起停止服務(wù)nrm use taobao || npm config set registry registry.npmmirror.com/

npm i vue-socket.io@3.0.10 -S  //個(gè)人使用了當(dāng)前版本

使用方式一 (官方用法)[全局掛載,不驗(yàn)證]

需注意:事件只有在訂閱后才可接接收返回消息(訂閱方法與后端約定名稱)。

實(shí)例創(chuàng)建后,全局掛載實(shí)例方法,this.$socket,this.sockets。

其中事件訂閱、取消與監(jiān)聽方法在this.sockets封裝;

this.$socket是socket.io實(shí)例中io的封裝。

// 全局掛載
// main.js  
import VueSocketIO from 'vue-socket.io'
Vue.use(new VueSocketIO({
  debug: true,// 生產(chǎn)環(huán)境關(guān)閉,打開可在控制臺查看socket連接和事件監(jiān)聽的信息
  options: {
    autoConnect: false //創(chuàng)建時(shí)是否自動連接,默認(rèn)關(guān)閉,使用時(shí)用open開啟鏈接
  },
  connection: 'http://127.0.0.1:9527' //鏈接地址
}))  
//1.全局掛載-全局使用
//main.js  
new Vue({
    sockets: {
        connecting() { console.log('正在連接') },
        connect() { console.log('連接成功') },
        disconnect() { console.log('斷開連接') },
        connect_failed() { console.log('連接失敗') },
        error() { console.log('錯(cuò)誤發(fā)生,并且無法被其他事件類型所處理') },
        reconnecting() { console.log('正在重連') },
        reconnect_failed() { console.log('重連失敗') },
        reconnect() { console.log('重連成功') },
        welcome: data => {//全局監(jiān)聽訂閱事件,需要與后端約定好
            console.log('welcome data', data)
        } 
    } 
}) 
//2. 全局掛載-組件內(nèi)使用
//demo.vue
<template> 
  <div> 
    <button @click="socketOpen">連接Socket</button>
    <button @click="closeSocket">斷開鏈接</button>
    <button @click="submsgContent(true)">訂閱事件</button>
    <button @click="submsgContent(false)">取消訂閱事件</button>
    <button @click="socketSendmsg">發(fā)送數(shù)據(jù)</button>
    <button @click="lockResult">查看鏈接參數(shù)</button>
  </div>
</template>
<script>
export default {
  beforeDestroy() { //訂閱事件記得要取消---否則多次訂閱會引發(fā)多次消息返回
    if (!this.$socket) return
    this.sockets.unsubscribe('msgContent')
    this.$socket.close()
  },
  sockets: { //監(jiān)聽用的是this.sockets   發(fā)送消息是this.$socket,不要弄混
        connecting() { console.log('正在連接') },
        connect() { console.log('連接成功') },
        disconnect() { console.log('斷開連接') },
        connect_failed() { console.log('連接失敗') },
        error() { console.log('錯(cuò)誤發(fā)生,并且無法被其他事件類型所處理') },
        reconnecting() { console.log('正在重連') },
        reconnect_failed() { console.log('重連失敗') },
        reconnect() { console.log('重連成功') },
        welcome: data => {//全局監(jiān)聽訂閱事件,需要與后端約定好
            console.log('welcome data', data)
        }
  },
  methods: {
    socketOpen() { 
      this.$socket.open()// 開始連接 socket
    },
    socketSendmsg() { // 發(fā)送消息
      this.$socket.emit('hello', '這里是客戶端')
    },
    lockResult() {
      console.log('鏈接狀態(tài)', this.$socket.connected)
      console.log('this.$socket', this.$socket)
      console.log('this.sockets', this.sockets)
    },
    closeSocket() {
      this.$socket.close()
    },
    submsgContent(flag) {  
        if (flag) { //事件訂閱
          this.sockets.subscribe('welcome', data => { //組件內(nèi)監(jiān)聽
            console.log('組件內(nèi)監(jiān)聽-welcome', data)
          })
        } else {//取消訂閱
          this.sockets.unsubscribe('welcome')
        } 
    }
  }
}
</script>  

使用方式二 (組件掛載使用)[可驗(yàn)證]

因在組件內(nèi)使用,所以可將邏輯寫在登錄后加載掛載組件,全局或指定頁面使用。

組件內(nèi)創(chuàng)建注意事項(xiàng):因vue-socket.io,在new.use()時(shí)掛載方法$socket到全局,在創(chuàng)建實(shí)例時(shí)掛載sockets監(jiān)聽對象到當(dāng)前實(shí)例,所以,在組件中使用后會導(dǎo)致以下問題:

問題:
 1. $socket可正常使用,與$socket也就是io相關(guān)的方法都可正常使用(例如:this.$socket.open()、close等等...)
 2. sockets相關(guān)方法無法使用(例如:this.sockets.unsubscribe、this.sockets.subscribe等等)
處理方式:使用socket.io原生方法,
 1. 事件訂閱 
    實(shí)例.emitter.addListener
 2. 取消訂閱
    實(shí)例.emitter.addListener 

 //demo.vue
 <template>
  <div> 
    <button @click="createSocket">創(chuàng)建socket</button>
    <div v-if="createSocketIO ? true:false ">
      <button @click="socketOpen">連接Socket</button>
      <button @click="closeSocket">斷開鏈接</button>
      <button @click="submsgContent(true)">訂閱事件</button>
      <button @click="submsgContent(false)">取消訂閱事件</button>
      <button @click="socketSendmsg">發(fā)送數(shù)據(jù)</button>
      <button @click="lockResult">查看鏈接參數(shù)</button>
    </div>
  </div>
</template>
<script> 
import VueSocketIO from 'vue-socket.io'
export default {
  data() {
    return {
      createSocketIO: null,
      createSocketEmitter: null
    }
  },
  beforeDestroy() { //訂閱事件記得要取消
    if (this.createSocketIO) {
      this.createSocketEmitter.removeListener('msgContent', this)
      this.createSocketIO.close()
    }
  },
  methods: {
   async createSocket() {//也可在頁面初始話調(diào)用  
      let socketUrl
      /* // 動態(tài)ip與token實(shí)現(xiàn),ip+端口可通過接口拿取,token及用戶信息可通過vuex拿取
            const userId = store.getters.userInfo.userId
            const ipResult = await getHostIp()
            if (ipResult.code !== 0) return
            const { ip, port } = ipResult.data
            const protocol = window.location.protocol
            const socketUrl = `${protocol}//${ip}:${port}?userId=${userId}`
            console.log('socketUrl', socketUrl)
       */    
      socketUrl = 'http://127.0.0.1:9527'
      const createSocketItem = new VueSocketIO({
        debug: true,
        options: {
          autoConnect: false,//默認(rèn)關(guān)閉,創(chuàng)建后打開,組件內(nèi)使用可直接打開,就不需要用io.open()
          transports: ['websocket'], 
          query: {  
              token: 77777777777 //攜帶的額外參數(shù)也可通過url拼接實(shí)現(xiàn)
          }
        },
        connection:socketUrl 
      })
      const { io, emitter } = createSocketItem
      io.query.ttt = 8888888888
      this.createSocketIO = io
      this.createSocketEmitter = emitter
      io.open()
      io.on('connecting', () => { console.log('正在連接---888') })
      io.on('connect', () => { console.log('連接成功---888') })
      io.on('disconnect', () => { console.log('斷開連接---888') })
      io.on('connect_failed', () => { console.log('連接失敗---888') })
      io.on('error', () => { console.log('錯(cuò)誤發(fā)生,并且無法被其他事件類型所處理') })
      io.on('reconnect_attempt', () => {console.log('觸發(fā)嘗試重新連接', 888)})
      io.on('reconnecting', () => { console.log('正在重連---888') })
      io.on('reconnect_failed', () => { console.log('重連失敗---888') })
      io.on('reconnect', () => { console.log('重連成功---888') })
      emitter.addListener('welcome', (data) => {
        console.log('data', data)
      }, this) 
    },
    socketOpen() {
      this.createSocketIO.open()
    },
    socketSendmsg() { // 發(fā)送消息
      this.createSocketIO.emit('hello', '這里是客戶端')
    },
    lockResult() {
      console.log('鏈接狀態(tài)', this.createSocketIO.connected)
    },
    closeSocket() {
      this.createSocketIO.close()
    },
    submsgContent(flag) {
      if (flag) {
        this.createSocketEmitter.addListener('welcome', (data) => {
          console.log('data', data)
        }, this)
      } else {
        this.createSocketEmitter.removeListener('welcome', this)
      } 
    }
  }
}
</script> 

使用方式三 (全局掛載使用)[可驗(yàn)證]

當(dāng)前方法實(shí)現(xiàn)類似直接使用socket.io,基本相當(dāng)于只是使用了vue-socket.io的庫與全局掛載的this.$scoket方法。

注: vue.use( new VueSocketIO({connection:'http://127.0.0.1:9527'})) 只將實(shí)例中io模塊掛載了this.$scoket

實(shí)現(xiàn)思路與遭遇問題:

  實(shí)現(xiàn):  

通過本地輪詢,實(shí)時(shí)獲取用戶登錄狀態(tài),用戶登錄后掛載全局方法 

問題:

同實(shí)現(xiàn)方式二問題,vue-socket.io,在new.use()時(shí)掛載方法$socket到全局(io模塊),在創(chuàng)建實(shí)例時(shí)掛載sockets監(jiān)聽對象到當(dāng)前實(shí)例;在輪詢拿到用戶當(dāng)前掛載相關(guān)方法時(shí),當(dāng)前項(xiàng)目實(shí)例已經(jīng)被創(chuàng)建,能拿到this.$socket,不能拿到this.sockets;需要使用頁面后置加載,或重新加載后正常,掛載方法才能正常使用

解決方式:

在創(chuàng)建實(shí)例時(shí),將除io,模塊的事件(emitter)與監(jiān)聽(listener)也掛載到全局,使用相關(guān)定義方法在mounted生命周期中進(jìn)行;登錄前盡量把數(shù)據(jù)存儲好后在進(jìn)入系統(tǒng)

使用示例:

//main.js 入口文件全局掛載
// import Vue from 'vue'
import router from '@/router'
import store from '@/store'
import App from './App'  
import '@/util/socket.js'  //使用全局掛載
Vue.config.productionTip = false
const saasVue = new Vue({
  router,
  store,
  i18n,
  render: h => h(App)
}).$mount('#app')
window.saasVue = saasVue 
// socket.js 全局方法實(shí)現(xiàn)
import Vue from 'vue'
import VueSocketIO from 'vue-socket.io'
import store from '@/store'
import { getHostIp } from '@/api/admin/message' //獲取后端動態(tài)ip地址
let socketIo, socketListener, socketEmitter
if (!getToken()) {
  const timer = setInterval(() => {
    console.count()
    if (!getToken()) return
    initSocket(getToken())
    window.clearInterval(timer)
  }, 1000)
} else { 
  initSocket(getToken())
}
function getToken() {//獲取登錄標(biāo)識---請修改為自己項(xiàng)目標(biāo)識
  return store.getters.access_token
}
async function initSocket(token) {
  const userId = store.getters.userInfo.userId //獲取登錄標(biāo)識---請修改為自己項(xiàng)目用戶id
  const ipResult = await getHostIp()
  if (ipResult.code !== 0) return
  const { ip, port } = ipResult.data
  const protocol = window.location.protocol
  const socketUrl = `${protocol}//${ip}:${port}?userId=${userId}`
  console.log('socketUrl', socketUrl)
  //const socketUrl = 'http://127.0.0.1:9527' //本地測試地址---nodejs服務(wù)代碼放后面
  const socket = new VueSocketIO({
    debug: process.env.NODE_ENV !== 'production',
    options: {
      autoConnect: false //已通過驗(yàn)證,全局使用可默認(rèn)打開,組件內(nèi)使用則默認(rèn)關(guān)閉,使用時(shí)在打開
    },
    connection: socketUrl
  })
  const { emitter, io, listener } = socket
  socketIo = io
  socketListener = listener
  socketEmitter = emitter
  if (process.env.NODE_ENV !== 'production') {// 與socket鏈接相關(guān)全局處理,與后端預(yù)定定義事件在組件內(nèi)訂閱使用
    io.on('connecting', () => { console.log('socketjs---正在連接') })
    io.on('connect', () => { console.log('socketjs---連接成功') })
    io.on('disconnect', () => { console.log('socketjs---斷開連接') })
    io.on('connect_failed', () => { console.log('socketjs---連接失敗') })
    io.on('error', () => { console.log('socketjs---錯(cuò)誤發(fā)生,并且無法被其他事件類型所處理') })
    io.on('reconnect_attempt', () => { console.log('socketjs---觸發(fā)嘗試重新連接')})
    io.on('reconnecting', () => { console.log('socketjs---正在重連') })
    io.on('reconnect_failed', () => { console.log('socketjs---重連失敗') })
    io.on('reconnect', () => { console.log('socketjs---重連成功') })
  }
  //   Vue.use(socket) //只是掛載了io模塊,存在已加載頁面無法訂閱問題,不如不使用,自己掛載方便
  Object.defineProperty(Vue.prototype, '$socketIo', { value: socketIo })
  Object.defineProperty(Vue.prototype, '$socketListener', { value: socketListener })
  Object.defineProperty(Vue.prototype, '$socketEmitter', { value: socketEmitter })
}
export default { socketIo, socketListener, socketEmitter } 

組件內(nèi)使用:

//demo.vue  訂閱事件與銷毀在組件中進(jìn)行
<template>
  <div> 
    <button @click="socketOpen">連接Socket</button>
    <button @click="closeSocket">斷開鏈接</button>
    <button @click="submsgContent(true)">訂閱事件</button>
    <button @click="submsgContent(false)">取消訂閱事件</button>
    <button @click="socketSendmsg">發(fā)送數(shù)據(jù)</button>
    <button @click="lockResult">查看鏈接參數(shù)</button>
  </div>
</template>
<script>
export default {
  beforeDestroy() { //訂閱事件記得要取消
    if (this.$socketIo) {
      this.$socketEmitter.removeListener('msgContent', this)
      this.$socketIo.close()
    }
  },
  mounted() {
    this.$socketIo.open()//初始化打開鏈接 
    this.$socketEmitter.addListener('welcome', (data) => {//組件初始化掛載后,訂閱后端事件
      console.log('data', data)
    }, this)
  },
  methods: {
    socketOpen() {
      this.$socketIo.open() 
    },
    socketSendmsg() { // 發(fā)送消息
      this.$socketIo.emit('hello', '這里是客戶端')
    },
    lockResult() {
      console.log('鏈接狀態(tài)', this.$socketIo.connected)
    },
    closeSocket() {
      this.$socketIo.close()
    },
    submsgContent(flag) {
      if (flag) {
        this.$socketEmitter.addListener('welcome', (data) => {
          console.log('data', data)
        }, this)
      } else {
        this.$socketEmitter.removeListener('welcome', this)
      } 
    }
  }
}
</script> 

使用方式推薦

方式一:適用于全局通知類業(yè)務(wù)類型多,不驗(yàn)證用戶登錄,一般是門口網(wǎng)站引流類型使用。

方法二:適用于通知類型較少的業(yè)務(wù)項(xiàng)目

方式三:適用項(xiàng)目通知類型多,業(yè)務(wù)場景模塊較多情況,全局掛載,每個(gè)頁面只需要做對應(yīng)方法訂閱,與銷毀;例如:系統(tǒng)消息+業(yè)務(wù)消息待辦通知,首屏監(jiān)控、大屏展示下多個(gè)模塊多訂閱場景。 

nodejs服務(wù)端本地demo代碼

相關(guān)依賴:

npm install socket.io@2.0.4 -S
// nodeSocket.js
var http = require('http')
var io = require('socket.io')
// 創(chuàng)建server服務(wù)
var server = http.createServer(function(req, res) {
  var headers = {}
  headers['Access-Control-Allow-Origin'] = '*'
  headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, DELETE, OPTIONS'
  headers['Access-Control-Allow-Credentials'] = true
  headers['Access-Control-Max-Age'] = '86400' // 24 hours
  headers['Access-Control-Allow-Headers'] = 'X-Requested-With, Access-Control-Allow-Origin, X-HTTP-Method-Override, Content-Type, Authorization, Accept'
  res.writeHead(200, headers)
  res.end()
})
// 啟動服務(wù)器  監(jiān)聽 1024 端口
server.listen(1024, function() {
  console.log('server runing at 127.0.0.1:1024')
})
// 啟動socket服務(wù)
var socket = io.listen(server, { origins: '*:*' })
socket.use((socket, next) => {
  const query = socket.handshake.query
  console.log('token', query.token)
  if (query.token) {
    return next()
  }
  return next(new Error('authentication error 鑒權(quán)失敗'))
})
// 監(jiān)聽客戶端連接
socket.on('connection', function(socket) {
  console.log('客戶端有連接') 
  // 監(jiān)聽客戶端斷開
  socket.on('disconnect', () => {
    console.log('客戶端斷開')
  })
  // 給客戶端發(fā)送消息
  setInterval(() => {
    socket.emit('welcome', '歡迎連接socket')
    console.count(1)
  }, 2000)
  // 監(jiān)聽客戶端消息
  socket.on('hello', data => {
    console.log('接收客戶端數(shù)據(jù)---:', data)
  })
}) 

 啟動:

node nodeSocket.js

總結(jié)

  • vue-socket.io使用版本注意,3.0.8、3.0.9有部分bug,感興趣的可以去試試;
  • nodejs模塊使用的socket.io版本注意,socket.io版本大于了2.0.4后使用方法有變化;
  • 消息訂閱同一方法可多次訂閱,訂閱幾次,后端一次返回了幾次訂閱消息。所以注意取消訂閱方法。
  • 同一訂閱方法,在不同頁面使用,銷毀后會取消所有使用當(dāng)前方法的訂閱消息。需要不同模塊與后端約定不同方法,根據(jù)項(xiàng)目消息架構(gòu)處理;

以上就是vue使用 vue-socket.io三種方式及采坑記錄實(shí)例解析的詳細(xì)內(nèi)容,更多關(guān)于vue使用vue-socket.io采坑的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue2?模版指令元素綁定事件執(zhí)行順序解析

    Vue2?模版指令元素綁定事件執(zhí)行順序解析

    這篇文章主要為大家介紹了Vue2?模版指令元素綁定事件執(zhí)行順序解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • vue3實(shí)現(xiàn)多個(gè)表格同時(shí)滾動并固定表頭

    vue3實(shí)現(xiàn)多個(gè)表格同時(shí)滾動并固定表頭

    這篇文章主要給大家介紹了vue3中多個(gè)表格怎么同時(shí)滾動并且固定表頭,文中通過代碼示例給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-02-02
  • vue中音頻wavesurfer.js的使用方法

    vue中音頻wavesurfer.js的使用方法

    這篇文章主要為大家詳細(xì)介紹了vue中音頻wavesurfer.js的使用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • 如何解決d3.event在v7版本無效影響zoom拖拽縮放問題

    如何解決d3.event在v7版本無效影響zoom拖拽縮放問題

    這篇文章主要介紹了如何解決d3.event在v7版本無效影響zoom拖拽縮放問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • vue使用css-rcurlyexpected等less報(bào)錯(cuò)問題

    vue使用css-rcurlyexpected等less報(bào)錯(cuò)問題

    這篇文章主要介紹了vue使用css-rcurlyexpected等less報(bào)錯(cuò)問題,具有很的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • OpenLayer基于vue的封裝使用教程

    OpenLayer基于vue的封裝使用教程

    這篇文章主要介紹了OpenLayer基于vue的封裝使用,openlayer使用的版本是"^6.4.3",引入了mapbox的樣式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • 解決vue中使用history.replaceState?更改url?vue?router?無法感知的問題

    解決vue中使用history.replaceState?更改url?vue?router?無法感知的問題

    這篇文章主要介紹了vue中使用history.replaceState?更改url?vue?router?無法感知的問題,本文給大家分享修復(fù)這個(gè)問題的方法,需要的朋友可以參考下
    2022-09-09
  • vant 中van-list的用法說明

    vant 中van-list的用法說明

    這篇文章主要介紹了vant 中van-list的用法說明,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • Vue + Vue-router 同名路由切換數(shù)據(jù)不更新的方法

    Vue + Vue-router 同名路由切換數(shù)據(jù)不更新的方法

    本篇文章主要介紹了Vue + Vue-router 同名路由切換數(shù)據(jù)不更新的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • VueCli4項(xiàng)目配置反向代理proxy的方法步驟

    VueCli4項(xiàng)目配置反向代理proxy的方法步驟

    這篇文章主要介紹了VueCli4項(xiàng)目配置反向代理proxy的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05

最新評論