Vue组件优雅的使用Vuex异步数据
前端:
Vue
+element
项目为前后端分离项目,通过
Ajax
交换数据。更新时间:2020-09-10 19:11:42
2020-09-10 19:11:42
- 拆分 vue 文件支持代码高亮
2020-05-23 22:02:45
0x1 缘起
今天在检查代码的时候发现了一个平时都忽略的问题,就是在组件使用vuex数据时,组件使用都是同步取的
vuex
值。关于vuex
的使用可以查看官网文档:https://vuex.vuejs.org/zh/ ,如果我们需要的vuex
里面的值是异步更新获取的,在网络和后台请求特别快的情况下不会有什么问题。但是网络慢或者后台数据返回较慢的情况下问题就来了。
0x2 案例
${app}
代表你的项目根目录,项目目录结构同大部分Vue
项目。
需求
我需要实现这样一个效果,我需要在
foo.vue
,bar.vue
,两个不同的页面建立一个使用相同信息的socket
连接,当我离开foo.vue
页面的时候断开连接,在bar.vue
页面的时候重新连接。而且我的socket连接信息(连接地址,端口等)来自于接口请求。
初次实现
在
App.vue
初始化的时候dispatch
一个action
去获取socket
的连接信息,然后在foo.vue
或者bar.vue
页面mounted
的时候进行连接。
Vuex
${app}/src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import api from '@/apis'
import handleError from '@/utils/HandleError'
Vue.use(Vuex)
export default new Vuex.Store({
strict: process.env.NODE_ENV !== 'production',
state: {
socketInfo: {
serverName: '',
host: '',
port: 8080
}
},
mutations: {
// Update token
UPDATE_SOCKET_INFO(state, {
socketInfo }) {
// state.socketInfo = socketInfo
// Update vuex token
Object.assign(state.socketInfo, socketInfo)
}
},
actions: {
// Get socket info
async GET_SOCKET_INFO({
commit }) {
// Rquest socket info
try {
const res = await api.Common.getSocketUrl()
// Success
if (res.success) {
commit('UPDATE_SOCKET_INFO', {
socketInfo: res.obj
})
}
} catch (e) {
// Handle api request exception
handleError.handleApiRequestException(e)
}
}
}
})
App.vue
${app}/src/App.vue
<!-- App -->
<div id="app"></div>
export default {
name: 'App',
mounted() {
// Get socket info
this.$store.dispatch('GET_SOCKET_INFO')
}
}
foo.vue
${app}/src/views/foo/foo.vue
import io from 'socket.io-client'
export default {
name: 'Foo',
mounted() {
const {
serverName, host, port } = this.$store.state.socketInfo
const socket = io(`ws://${
host}:${
port}`, {
path: `/${
serverName}`,
transports: ['websocket', 'polling']
})
}
}
❓ 问题
问题很显而易见,当我直接访问
foo.vue
页面的时候,如果我的后台api或者网络请求慢的情况下,我的vuex
的store
还未更新,也就是App.vue
的请求还未回来,这个时候foo.vue
页面的mounted
生命周期函数已经执行,很显然,我需要的socket
连接信息拿不到,这个时候控制台就会飘红。
WebSocket connection to 'ws://%27%27/''/?EIO=3&transport=websocket' failed: Error in connection establishment: net::ERR_NAME_NOT_RESOLVED
✅ 第一次解决
既然是需要等到请求回来在连接,那么好办了,我在
foo.vue
页面也获取一次socket
的连接信息获取成功了在进行连接,此时foo.vue
代码变成了如下这样
foo.vue
${app}/src/views/foo/foo.vue
import io from 'socket.io-client'