Vuex之Getters详解

本文详细介绍了Vuex中的Getters,包括其基本用法、如何直接调用,以及进阶的mapGetters用法。通过示例展示了在单store、分模块store以及重命名Getters属性的方法,并探讨了mapGetters的工作原理。最后,文章鼓励读者通过理解源码尝试不依赖mapGetters来调用Getters,以提升开发效率。
部署运行你感兴趣的模型镜像

原文地址: https://www.jeremyjone.com/543/, 转载请注明


file

作为Vue的状态管理工具,Vuex的使用率相当之高。Vuex具有4个属性,state,getters,actions,和mutations。

今天来讨论一下getters。它相当于vue的computed计算属性。每当state中的值变化时,它也会自动更新。这个在我们需要那些稍微对state中的属性进行改造的属性时很有帮助。在实际生产中,我们会大量使用getters,而state会相对较少。

getters的基本用法,直接调用

首先在根目录下创建一个store.js

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

// 状态对象
const state = {
  myList: ["a", "b", "c", "d", "e"]
};

// getters计算属性对象
const getters = {
  getObjByIndex(state): {
    return function(index) {
      return state.myList[index];
    };
  }
};

// 包含多个用于更新state属性的函数的对象
const mutations = {};

// 包含多个事件回调函数的对象
const actions = {};

export default new Vuex.Store({
  state,
  getters,
  mutations,
  actions
})

然后我们在main.js中引用store,并添加到Vue实例中:

import store from "@/store";

new Vue({
  store,  // 将store对象添加到Vue实例
  render: h => h(App)
}).$mount("#app");

这样就完成了最简单的Vuex加载。

调用方案

加载之后,我们就可以在任何Vue组件中使用store,具体方法:

this.$store.getters["getObjByIndex"](0)  // 或 this.$store.getters.getObjByIndex(0)

因为JavaScript的对象允许我们使用点的方式或者中括号的方式调用对象内容,所以这两种方式都可以调出getters中的属性信息。

  • **注意:**我这里使用了闭包的形态,因为在getters中是属性,不是函数,所以我们不能直接传参调用,但是在实际使用中我们经常需要一些类似idindex这样的参数来调用某一个序列中的某一个值。为了解决这个问题,可以使用闭包的方案,具体闭包的功能这里不赘述。

因为Vuexstore本身就是一个对象管理,我们都可以通过直接调用的方式来操作。但是每一次都要写this.$store.getters.xxx这种形式真的很麻烦,有没有简单的方式呢?Vuex给了我们很好的解决方案:mapGetters

getters的进阶用法,使用mapGetters简化代码

对于Vue的组件来说,我们可以使用mapGetters函数,具体方法如下:

先看用法

mapGetters是官方提供的map系列函数中的一个,它会直接返回一个对象,将我们需要的 对象 / 函数 直接加载到组件中。

单store

假设我们还是使用上述创建的store,那么它在Vue组件中可以这样使用:

import { mapGetters } from "vuex";
export default {
    computed: {
	    ...mapGetters(["getObjByIndex"]);  // 导入getters的属性
	}
}

这样就可以在这个Vue组件中使用这个属性了。

getObjByIndex(0); // 会直接取值
分模块store

如果我们的项目很大,单模块的store完全不能满足我们的需求,这个时候就需要分模块。

再比如我们现在有一个叫myStore模块的store

const state = {
  myList: []
};

const getters = {
  getObjByIndex(state): {
    return function(index) {
      return state.myList[index];
    };
  }
};

const mutations = {};

const actions = {};

export const myStore = {
  namespaced: true,
  state,
  getters,
  actions,
  mutations
};

该仓库的模块名为myStore,继续导入到Vue组件中:

import { mapGetters } from "vuex";

export default {
    computed: {
	    // 这个时候就需要在导入时添加上模块名
	    ...mapGetters("myStore", ["getObjByIndex"]);
	}
}
重命名

如果想重命名该属性,可以使用如下语句,这个对于所有模块都是一样的:

import { mapGetters } from "vuex";

export default {
    computed: {
	    // 对属性重命名,这样我们就可以在该组件中使用 getMyObj 了。
	    ...mapGetters("myStore", {getMyObj: "getObjByIndex"});
	}
}

深入理解

为何我们可以这样方便的使用mapGetters,我们可以通过源码来找寻答案:

源码很短:

/**
 * Reduce the code which written in Vue.js for getting the getters
 * @param {String} [namespace] - Module's namespace
 * @param {Object|Array} getters
 * @return {Object}
 */
var mapGetters = normalizeNamespace(function (namespace, getters) {
  var res = {};
  normalizeMap(getters).forEach(function (ref) {
    var key = ref.key;
    var val = ref.val;

    // The namespace has been mutated by normalizeNamespace
    val = namespace + val;
    res[key] = function mappedGetter () {
      if (namespace && !getModuleByNamespace(this.$store, 'mapGetters', namespace)) {
        return
      }
      if (!(val in this.$store.getters)) {
        console.error(("[vuex] unknown getter: " + val));
        return
      }
      return this.$store.getters[val]
    };
    // mark vuex getter for devtools
    res[key].vuex = true;
  });
  return res
});
具体来看

1、首先调用了通用的函数normalizeNamespace,而这个函数就是将传入的改成namespace/getters的分割样式,如果没有namespace,那么直接返回getters,具体函数如下:

function normalizeNamespace (fn) {
  return function (namespace, map) {
    if (typeof namespace !== 'string') {
      map = namespace;
      namespace = '';
    } else if (namespace.charAt(namespace.length - 1) !== '/') {
      namespace += '/';
    }
    return fn(namespace, map)
  }
}

2、迭代函数normalizeMap只是将输入的getters对应成store的内部属性,具体函数如下:

function normalizeMap (map) {
  return Array.isArray(map)
    ? map.map(function (key) { return ({ key: key, val: key }); })
    : Object.keys(map).map(function (key) { return ({ key: key, val: map[key] });
  })
}

这段函数也说明了为什么我们可以使用对象来更改名称,它依旧会映射我们传入的value

3、查找属性。之后的代码就很简单了,就是简单的判断+查找,如果找到对应的属性,最后返回 this.$store.getters[val]

这就是mapGetters的大体工作流程。

学以致用

看过源码,那么我们试着不用mapGetters来调用。听起来没什么用,但是实际应用中,也会经常使用该方法,比如在js模型中,我们就需要手动调用。

首先引用store

import store from "@/store";

然后直接使用store调用一开始我们定义的属性:

var myObj = store.getters["myStore/getObjByIndex"]

已经成功调取,是不是很方便。

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

### Vuex 状态管理库的详细使用方法 Vuex 是 Vue.js 应用的状态管理模式,提供了一种集中式存储和管理应用状态的方法。它通过单一的状态树(store)来维护所有组件的状态,并且确保状态的变化是可预测的。 #### 核心概念 Vuex 的核心概念包括 store、actions、mutations 和 getters: - **Store**:这是保存应用状态的地方。所有的状态都应被包含在 store 中。 - **Mutations**:用于同步更改状态的操作。每个 mutation 都有一个类型(type)和一个处理器函数(handler),该处理器直接修改状态。 - **Actions**:与 mutations 类似,但不同之处在于 actions 提交的是 mutations 而不是直接变更状态,并且可以包含任意异步操作。 - **Getters**:从 store 中派生出一些状态的计算属性,类似于 Vue 组件中的 computed 属性。 这些核心概念共同构成了一个清晰的状态管理流程,使得状态变化更加透明和易于调试 [^1]。 #### 异步操作处理 当需要执行异步操作时,应该使用 actions 来处理。例如,在用户登录后获取数据的情况下,可以通过 dispatch 方法调用 action,然后在这个 action 内部提交 mutation 来更新状态。这样做的好处是可以将异步逻辑从组件中解耦出来,保持组件的纯净性 [^2]。 ```javascript // 示例代码展示如何定义带有异步操作的action const store = new Vuex.Store({ state: { items: [] }, mutations: { setItems(state, payload) { state.items = payload; } }, actions: { fetchItems({ commit }) { // 模拟API请求 setTimeout(() => { const data = ['Item 1', 'Item 2']; commit('setItems', data); }, 1000); } } }); ``` #### 模块化组织状态 对于大型项目来说,随着状态数量的增长,单一的 store 可能会变得非常臃肿。为了解决这个问题,Vuex 支持模块化的结构,允许我们将 store 分割成多个模块。每个模块拥有自己的 state、mutations、actions 和 getters。 ```javascript // moduleA.js export default { state: () => ({ count: 0 }), mutations: { incrementCount(state) { state.count++; } }, actions: { increment({ commit }) { commit('incrementCount'); } }, getters: { doubleCount: state => state.count * 2 } } // store/index.js import Vue from "vue"; import Vuex from "vuex"; import moduleA from './modules/moduleA'; Vue.use(Vuex); const store = new Vuex.Store({ modules: { a: moduleA } }); export default store; ``` 通过这种方式,我们可以创建出可复用的状态管理模块,提高代码的可维护性和可扩展性 [^3]。 #### 辅助函数 为了简化状态映射到组件的过程,Vuex 提供了一些辅助函数如 `mapState`、`mapMutations`、`mapActions` 和 `mapGetters`。这些工具可以帮助我们更方便地访问或触发 store 中的状态和行为。 ```javascript // 使用mapState辅助函数简化状态映射 import { mapState } from 'vuex'; export default { computed: mapState({ // 箭头函数使代码更简洁 count: state => state.count, // 字符串参数等价于 `state => state.count` countAlias: 'count', // 如果需要访问局部状态,则必须使用常规函数 countPlusLocalState(state) { return state.count + this.localCount; } }) } ``` 利用这些辅助函数,开发者能够以更加优雅的方式集成 Vuex 到他们的 Vue 应用程序中 [^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值