vuex通过getters访问数据为undefined问题及解决

 更新时间:2022年08月31日 15:43:46   作者:qiqingfu  
这篇文章主要介绍了vuex通过getters访问数据为undefined问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

getters访问数据为undefined问题

本篇文章可能对你的帮助不大, 只是个人开发中的一些记录。不同的业务和应用场景可能问题不同。

在通过 uni-app 开发商城时,用户快捷登录之后,服务器返回一个 token 数据,我将其同步到 vuex module下的 user 模块中。

然后从登录页返回到用户页,并发起 http 请求,获取用户的个人信息。

但是在请求时,我会在请求拦截器中获取 vuex 中的 token 数据。如果存在就携带到请求头中和服务器做 OAuth 验证。如果不存在就直接不携带 token。

用户登录成功之后,返回到用户页发起请求,但是获取用户信息接口是必须做 OAuth 验证的。问题在于在请求拦截器中 不能通过 vuex 的 getter 正确获取到 token值,而是返回 undefined。

request.js

import Http from "../xxx/http";
import store from "../sotre";
const request = new Http({
  baseURL: xxxxx,
  timeout: 50000,
  // 省略
});
request.interceptors.request.use((config) => {
  let token, g_t;
  if (
    (g_t = store.getters[`user/token`]) ||
    (g_t = Storage.get(USER_TOKEN_KEY))
  ) {
    token = g_t.token || null;
  }
  if (token) {
    config.header["Authorization"] = "Bearer " + token;
  }
  return config;
});

问题在于 g_t = store.getters[user/token] 获取的值为 undefined。

经过排查发现,vuex 中 getters 下的通过 state 获取的字段实现没有在 state 中定义。而是通过异步登录之后,才将其设置到 user 模块下的 state 中,使其变为不是响应式的。

写一个类似例子

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <p>姓名: {{ realName }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3.3.0/dist/vuex.js"></script>
<script type="module">
  Vue.use(Vuex);
  const store = new Vuex.Store({
    state: {},
    mutations: {
      change(state, data) {
        state.name = data;
      }
    },
    getters: {
      name: state => {
        return state.name;
      }
    }
  });
  new Vue({
    el: "#app",
    store,
    data: {
      message: "Hello"
    },
    computed: {
      realName() {
        return this.$store.getters.name;
      }
    },
    created() {
      setTimeout(() => {
        this.$store.commit('change', 'zhangsan');
      })
    }
  })
</script>
</body>
</html>

异步代码执行的时候, state 中并没有 name 属性。所以一开始 getters 下的 realName 就算是 undefined。异步代码提交的 commit,在想 state 中新增 name 字段,但是它已不是响应式的。

解决方法:

就是提前在 state 中定义 getters 需要的某些字段,异步变更 state 中的字段它也是响应式的。getters 的值也会进行计算。

getters 类似于 vue 中的计算属性。

修改上面的代码为:

const store = new Vuex.Store({
    state: {
        name: ""
    },
    // 省略...
  })  

这样 getters 的值会根据 name的值改变而进行计算。

项目中的代码比上面的例子更复杂,但是问题是类似的。经过排查后才发现,所以在博客中总结一下。

小结:使用 vuex 时, getters 中需要计算的 state 属性一定要提前声明,使其成为响应式的值。

vuex getters(组件mounted调用)使用注意

逻辑

  • state存储数据(一开始为空数据,通过网络请求后更新数据)
  • 在组件mounted中先调用actions方法通过mutations更新state数据,
  • 接着组件mounted在调用getters 操作state中的数据,供组件使用
mounted(){
    // 进入组件立即发送网络请求获取商品信息
    this.$store.dispatch('detail/getCommdityInfo',this.skuId)
    console.log(this.skuInfo) //为undefined
    console.log(this.cateNav) //控制台报错
}
state: {
    commdityData:{}
  },
  mutations: {
    SET_COMMDITY_LIST(state,value){
      state.commdityData = null
      // 将商品信息存入组件内
      state.commdityData = value
      console.log('state.commdityData',state.commdityData)
    }
  },
  actions: {  
    async getCommdityInfo(context,query){
      const res = await getCommdityDetail(query)
      context.commit('SET_COMMDITY_LIST',res.data.data)
    }
  },
  getters:{
    skuInfo:state => state.commdityData.skuInfo,
    cateNav:state => {
        const {category1Name,category2Name,category3Name} = state.commdityData.categoryView 
        return [category1Name,category2Name,category3Name]
    },
    
  }

结果报错:组件在mouted 调用getters属性时,getters属性读取state数据(一开始为空),读取不到数据

**原因:**组件调用actions执行异步网络请求,通过mutations更新state数据还没有来得及执行

解决方案

更改getters中操作数据的属性,try-catch错误处理

cateNav:state => {
      // 使用情景,组件在mounted中调用,getters 的属性时,此时state未更新;解构会出错,所以要错误处理!!
      try{
        const {category1Name,category2Name,category3Name} = state.commdityData.categoryView 
        return [category1Name,category2Name,category3Name]
      }
      catch{
        return {}
      }
    },

!!!注意:在组件的methods中写方法调用则可正常使用getters的数据!! 

控制台输出:

1:mounted 输出

2:methods 方法的输出

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Vue项目中使用jquery的简单方法

    Vue项目中使用jquery的简单方法

    这篇文章主要给大家介绍了关于Vue项目中使用jquery的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Vue具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-05-05
  • vue实现条件判断动态绑定样式的方法

    vue实现条件判断动态绑定样式的方法

    今天小编就为大家分享一篇vue实现条件判断动态绑定样式的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • Vuex中actions优雅处理接口请求的方法

    Vuex中actions优雅处理接口请求的方法

    在项目开发中,如果使用到了 vuex,通常我会将所有的接口请求单独用一个文件管理,这篇文章主要介绍了Vuex中actions如何优雅处理接口请求,业务逻辑写在 actions 中,本文给大家分享完整流程需要的朋友可以参考下
    2022-11-11
  • 使用form-create动态生成vue自定义组件和嵌套表单组件

    使用form-create动态生成vue自定义组件和嵌套表单组件

    这篇文章主要介绍了使用form-create动态生成vue自定义组件和嵌套表单组件,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • 关于Element Loading的全局使用(自定义Loading)

    关于Element Loading的全局使用(自定义Loading)

    这篇文章主要介绍了关于Element Loading的全局使用(自定义Loading),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • 带你理解vue中的v-bind

    带你理解vue中的v-bind

    如果你写过vue,对v-bind这个指令一定不陌生。 下面小编将从源码层面去带大家剖析一下v-bind背后的原理,需要的小伙伴可以参考下面章的具体内容
    2021-09-09
  • vue中this.$emit使用方法的实际案例

    vue中this.$emit使用方法的实际案例

    this.$emit()的作用大家应该也都知道,主要用于子组件像父组件传值,这篇文章主要给大家介绍了关于vue中this.$emit使用方法的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • Vue-cli集成axios请求出现CORS跨域问题及解决

    Vue-cli集成axios请求出现CORS跨域问题及解决

    这篇文章主要介绍了Vue-cli集成axios请求出现CORS跨域问题及解决方案,具有很好的参考价值,希望对大家有所帮助,
    2023-10-10
  • vite(vue3)配置内网ip访问的方法步骤

    vite(vue3)配置内网ip访问的方法步骤

    Vite是一个快速的构建工具,Vue3是一个流行的JavaScript框架,下面这篇文章主要给大家介绍了关于vite(vue3)配置内网ip访问的方法步骤,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-05-05
  • VUE项目中调用高德地图的全流程讲解

    VUE项目中调用高德地图的全流程讲解

    这篇文章主要介绍了VUE项目中调用高德地图的全流程讲解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08

最新评论