使用vuex全局封装方法(以连接websocket,调用websocket方法为例)

Vuex 注入 Vue 生命周期的过程:https://mp.weixin.qq.com/s/WnRMCArDMy-PiFLprmMmCg

一、首先,想谈一下什么时候使用vuex:

(1)如果数据还有其他组件复用,建议放在vuex,比如在我所实现的项目中,实现了在线聊天功能,其中的对话框是有多个组件实现,而用户名等相关信息在各个组件中都需要使用;
(2)如果需要跨多级组件传递数据,建议放在vuex;
(3)需要持久化的数据(如登录后用户的信息),建议放在vuex,同样在我所实现的项目中,登录后用户的信息是放在了vuex中,需要使用的地方直接调用;
(4)跟当前业务组件强相关的数据,可以放在组件内;

以下文章更加详细的描述了什么场景下及为什么使用vuex:https://juejin.im/post/5b8e4b40f265da437174cbfe

vuex和浏览器缓存:https://segmentfault.com/q/1010000014557487

首先,要区别 vuex 和 浏览器缓存 的区别。

vuex 的设计是将数据存在一个 对象树的变量中,我们的应用(vue应用)从这个变量中取数据,然后供应用使用,当将当前页面关闭,  vuex 中的变量会随着消失,重新打开页面的时候,需要重新生成。
而,浏览器缓存(cookie,localstorage等)是将数据存到浏览器的某个地方,关闭页面,不会自动清空这些数据,当再次打开这个页面时,还是能取到之前存在浏览器上的数据(cookie,localstorage等)。
要使用  vuex 还是使用浏览器缓存,要看具体的业务场景。比如:像用户校验的  token 就可以存在  cookie 中,因为用户再次登录的时候能用到。而像 用户的权限数据,这些是有一定安全性考虑,且不同用户的权限不同,放在  vuex 中更合理,用户退出时,自动销毁。

其次,vuex 中的 state 是单向的,也可以异步操作,这两个没有冲突。

vuex 中的  state 的设计思路是保证数据的一致性和连续性,而让  state 中的值只能通过  action 来发起  commit,进而改变  state 中的值。
而, action 中是  同步 还是  异步,都是 单向地改变  state 中的值。

二、接下来讲vuex是什么?

该介绍来自官网:https://vuex.vuejs.org/zh/

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

  • 使用vuex全局封装方法(以连接websocket,调用websocket方法为例)_第1张图片
  • 每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:

  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

  • 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

  • 通过在根实例中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问到。

三、从项目出发,实现在线聊天

先讲一下我写这篇文章的背景,我们有一个功能是实现聊天功能。在上一篇文章中也讲到了,我需要连接websocket,而连接websocket要求用户在登录系统的那一刻就要实现websocket的连接,这就要求我定义全局的连接,其方法比如send,onmessage等方法在需要的地方直接调用即可。

因此我采用了vuex的方式,在vuex的modules下新建了websocket.js文件,其中的代码如下所示:

import store from './user'
const state = {
  websock: null
}

const mutations = {
  STAFF_UPDATEWEBSOCKET (state, websock) {
    state.websock = websock
  }
  // STAFF_SEND (state, text) {
  //   state.websock.send(text)
  // }
}

// 实现websocket的连接,需要携带参数token
const actions = {
  // 用到 ES2015 的参数解构来简化代码(特别是我们需要调用 commit 很多次的时候)
  STAFF_WEBSOCKET ({ commit }) {
    let token = encodeURI('Bearer ' + store.state.token)
    const wsuri = 'wss://XXXXXXXXX/?Authorization=' + token + '&EIO=3&transport=websocket'
    commit('STAFF_UPDATEWEBSOCKET', new WebSocket(wsuri))
    // 只有定义了onopen方法,才能继续实现接收消息,即在使用的地方调用onmessage方法。
    state.websock.onopen = function () {
    }
    // 心跳包,30s左右无数据浏览器会断开连接Heartbeat
    setInterval(function () {
      state.websock.send(JSON.stringify({
        'heart': true
      }))
    }, 30000)
  }
}

// 该部分为了获取websocket的相关方法。会发现此处跟mutations 里的写法是类似的,但是,想使用return,需要将相关数据写在getters里面。
const getters = {
  STAFF_UPDATE (state) {
    return state.websock
  }
}
export default {
  state,
  mutations,
  actions,
  getters
}

 相关代码注释在上述代码中已经有了体现,使用方法在下面的代码中:

1.调用websocket的send方法,即点击发送的时候,会调用send方法,将消息发送给服务端,下述代码是针对不同的定义方式,所采取的不同方法,比如,第三个方法是取得getters中的;第二个方法是取得mutations中的注释的STAFF_SEND中的方法;第一个是取得actions中定义的方法。

乍一眼看上去感觉多此一举,我们直接分发 mutation 岂不更方便?实际上并非如此,还记得 mutation 必须同步执行这个限制么?Action 就不受约束!我们可以在 action 内部执行异步操作

// Action 通过 store.dispatch 方法触发
this.$store.dispatch('STAFF_WEBSOCKET')
// this.$store.commit('STAFF_SEND').send('这是来自客户端的消息')
this.$store.getters.STAFF_UPDATE.send('sdfsfs')

Actions 支持同样的载荷方式和对象方式进行分发:

// 以载荷形式分发
store.dispatch('incrementAsync', {
  amount: 10
})

// 以对象形式分发
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

 

 2.通过websocket实现接收来自服务端的消息,实现方式如下代码:

onmessage () {
  let that = this
  this.$store.getters.STAFF_UPDATE.onmessage = function (evt) {
  let message = JSON.parse(evt.data)
  that.messages.push({
     content: message.content,
     self: false
  })
 }
}

关键是从getters中获取onmessage方法,上面强调过了,在调用该方法之前需要实现onopen方法。

如上,就可以实现聊天了。

你可能感兴趣的:(vue)