【前端笔记】Vuex快速使用

栏目: JavaScript · 发布时间: 6年前

内容简介:本文对 Vuex 官方文档重新组织编排,希望正在学习 Vue 的同学们,在阅读后可快速使用 Vuex。开始使用 Vuex,把状态拿到应用外部管理,Vuex管这个管理状态的玩意叫所谓状态管理,无非就是

本文对 Vuex 官方文档重新组织编排,希望正在学习 Vue 的同学们,在阅读后可快速使用 Vuex。

开始使用 Vuex,把状态拿到应用外部管理,Vuex管这个管理状态的玩意叫 Store ,一个完全独立的应用,他只负责状态管理。尝试把 Vuex 应用和 Vue 应用划清界限,

  • 一个 Vuex 应用,做状态管理,可以理解是 Model 层
  • 一个 Vue 应用,仅负责数据展示,纯纯的 View 层

Vuex 应用

所谓状态管理,无非就是 定义状态,修改状态

定义 state

在 Vuex 里定义状态,我们需要 new 一个 Store 出来,每一个 Vuex 应用的核心就是 store(仓库)。

// store.js
import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
    count: 0
  }
});

export default store;
复制代码

以上代码创建了一个 store, store.state 里定义了状态。与在 Vue 里定义 data 没有任何区别,

下面修改状态。

直接修改

如果你想快点用上 Vuex,你可以在组件里直接修改 store 里的 state,(直接修改的意思就是,用点操作修改)

state.count = 2;
复制代码

虽然这样可以正常工作,但在 严格模式 下会报错, 更改 store 中的状态的唯一方法应该是提交 mutation

严格模式

开启严格模式,仅需在创建 store 的时候传入 strict: true

const store = new Vuex.Store({
  strict: true
});
复制代码

在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。

mutation

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。

Vuex.Store 的构造器选项中,有一个 mutation 选项,这个选项就像是事件注册:key 是一个字符串表示 mutation 的类型(type),value 是一个回调函数(handler),

这个回调函数就是我们实际进行状态更改的地方,它有两个入参,第一个参数是 state,就是 store 里的 state;第二个参数是 Payload,这是提交 mutation 时候额外传入的参数。

定义 mutation

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment(state) {
      state.count++; // 变更状态
    }
  }
});
复制代码

提交 mutation

上面定义了 mutation,要唤醒一个 mutation handler,唯一的接口是 store.commit ,如果你熟悉事件监听,commit 就类似于 Vue 的 $emit ,jquery 的 trigger

可想而知,commit 方法传参必须至少有一个能区分 mutation 的唯一标识,这个标识就是 type

commit 参数是对象

当 commit 的参数是一个对象的时候,对象里必须要有 type 字段,除了 type 字段,你还可以添加额外任意字段为载荷(payload)。

// 对象风格的提交方式
store.commit({
  type: "increment",
  amount: 10
});
复制代码

type 做第一参数

把 type 和 payload 分开也是个不错的选择,可以把 type 单独拿出来当第一个参数,以 commit(type,[payload]) 的形式提交,官方称此为 以载荷形式提交

store.commit("increment");
store.commit("increment", 10);
store.commit("increment", { count: 2 });
复制代码

在大多数情况下,payload 应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读。

到这里我们已经知道如何定义 mutation 和提交 mutation 了,commit 接口很简单,但在哪里使用呢?有两个地方用

store.commit

Action

状态管理不过就是定义 state 和修改 state,mutation 已经可以修改 state 了,为什么还需要 action?

同步和异步

在 Vuex 中,mutation 都是同步事务,在 mutation 中混合异步调用会导致你的程序很难调试。

例如,当你调用了两个包含异步回调的 mutation 来改变状态,你怎么知道什么时候回调和哪个先回调呢?这就是为什么我们要区分这两个概念。

Action 确实和 mutation 很类似,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

注册 action:

注册 action 就跟定义 mutation 一样,除了 handler 的入参不同。

Action 函数的入参是一个与 store 实例具有相同方法和属性的 context 对象。因此可以

context.commit
context.state
context.getters
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  actions: {
    increment(context) {
      context.commit("increment");
    }
  }
});
复制代码

分发 Action

Action 通过 store.dispatch 方法触发:

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

// 以对象形式分发
store.dispatch({
  type: "incrementAsync",
  amount: 10
});
复制代码

组合 Action

store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise,因此,通过   async / await ,很方便控制流程

actions: {
  async actionA ({ commit }) {
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
}
复制代码

表单处理

表单的问题在于使用 v-model 时候, v-model 会试图直接修改 state,而 Vuex 在严格模式下是不允许直接修改 state 的。

很容易解决,只要我们把修改 state 的行为按 Vuex 的要求以 commit mutation 方式修改即可。

有两种方式。

用“Vuex 的思维”解决

抛弃 v-model 指令,自己去实现 v-model 双向绑定,非常简单,

  • input 标签的 value 属性绑定对应从 store 中映射来的计算属性,
  • 监听 input 事件,用 commit mutation 的方式,修改 store 里的 state。
<input :value="message" @input="updateMessage" />
复制代码
computed: {
  ...mapState({
    message: state => state.obj.message
  })
},

methods: {
  updateMessage (e) {
    this.$store.commit('updateMessage', e.target.value)
  }
}

复制代码

store 中的 mutation 函数:

mutations: {
  updateMessage (state, message) {
    state.obj.message = message
  }
}
复制代码

用 Vue 计算属性解决

如果坚持使用 v-model ,可以在 Vue 里对 v-model 绑定的计算属性设置 set 行为。

<input v-model="message" />
复制代码
computed: {
  message: {
    get () {
      return this.$store.state.obj.message
    },
    set (value) {
      this.$store.commit('updateMessage', value)
    }
  }
}
复制代码

使用 Vuex 进行状态管理,到此结束。

从 flux 架构来看,三个核心, StateMutationAction ,已经足够了,总结一下其实很简单, 同步 commit mutation,异步 dispatch action

核心原则

  • 应用层级的状态应该集中到单个 store 对象中。
  • 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
  • 异步逻辑都应该封装到 action 里面。

记住这些原则,开始动手把 Vuex 集成到 Vue 项目中吧,至于一些更多的概念,都是些锦上添花的东西。

Vue 应用使用 Vuex

Vuex 的常用 api 上面都涉及到了,使用思路就是

  • 定义状态:通过 new Vuex.Store({}) 创建一个 store 实例,定义 state,getters,actions,mutations。
  • 改变状态:使用 store.commit 提交 mutation ,使用 store.dispatch 分发 actions

现在状态管理的部分已经全部由 store 实例去管理了,如何在 Vue 组件中使用 store,非常简单,一点也不神奇。

store.js 文件里我们创建了 store 实例并将其导出了(export),按照 js 模块化的知识,我们只要在需要的地方导入它就可以直接使用了。

组件引入 store

可以在需要的组件里直接引入,就像引入一个普通的 js 一样。

import store from "path/to/store.js";
复制代码

组件中引入了 store,就可以直接通过 store.state 引用 state,以及直接使用 store 实例简洁的 api,真的就是这么简单。

store.state.count = 2; // 直接修改,并不建议
store.commit(); // 在 store 中调用 mutation
store.dispatch("increment"); // 在 store 中分发 action
复制代码

我们往往需要在 Vue 组件的 template 中展示状态,由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在 计算属性 中返回某个状态:

import store from "path/to/store.js";
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count() {
      return store.state.count;
    }
  }
};
复制代码

每当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。

其实到现在为止,对于在 Vue 中使用 Vuex 就已经足够了。下面的东西其实可以不用看了,但 Vuex 还是提供了一些方便我们使用的方式,锦上添花。

组件中引入的方式,缺点:这种模式导致组件依赖全局状态单例。在模块化的构建系统中,在每个需要使用 state 的组件中需要频繁地导入。

全局引入 store

Vuex 通过 store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中:

// app.js
import Vue from "vue";

import store from "path/to/store.js";

const app = new Vue({
  store // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
});
复制代码

通过在 根实例 中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问到。这样我们就不用每个组件单独引入了。

this.$store.state.count = 2; // 直接修改,并不建议
this.$store.commit("", {}); // 直接在组件中提交 mutation
this.$store.dispatch("increment"); // 在组件中分发 action
复制代码

组件绑定的辅助函数

  • mapState
  • mapGetters
  • mapMutations
  • mapActions

既然是辅助,就不是必须的东西,辅助函数可以方便的把 Vuex 中的 state,getter,mutation,action 映射到组件,方便调用。

更多概念

Getter

如果你很喜欢 Vue 提供的计算属性(computed),Vuex 允许在 store 中定义“getter”(可以认为是 store 的计算属性)。

但对状态管理来说,Getter 其实并不是必须的,如果你需要的话,可以查看文档使用。

Module

模块化并不是状态管理的概念,也不是必须的,但如果应用十分复杂,将 store 分割成模块(module)会是一个必经之路,Vuex 提供了模块化选项,需要可查看文档。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Design and Analysis of Distributed Algorithms (Wiley Series on P

Design and Analysis of Distributed Algorithms (Wiley Series on P

Nicola Santoro / Wiley-Interscience / 2006-10-27 / USD 140.95

This text is based on a simple and fully reactive computational model that allows for intuitive comprehension and logical designs. The principles and techniques presented can be applied to any distrib......一起来看看 《Design and Analysis of Distributed Algorithms (Wiley Series on P》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具