vuex详解及入门案例

简介

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化

适用场景:解决多层嵌套组件之间的通信问题,或是为了更好地管理应用中错综复杂的状态关系,一般用于中大型 web 单页应用中对应用的状态进行管理.
经典案例:购物车功能,音乐播放以及登录功能等

使用

  1. 在当前工程下载Vuex模块 $ npm install vuex --save
  2. 新建src/store/index.js, 引入Vuex模块,
  3. 确保Vue.use(Vuex) 让Vue集成Vuex的功能
  4. 然后实例化Vuex的Store仓库对象new Vuex.Store({}), 并向外暴露这个Store对象
  5. 在main.js入口中, 引入store文件, 注入到Vue实例中
    到此, 我们vuex就已经成功集成到了Vue项目中

核心概念

state(全局变量)

好比data, 定义变量的地方
​ Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。

state: {
    shopCarArr: [1, 2, 3, 4] // 用于装载购物车里的数据
  }
访问: this.$store.state.shopCarArr
mutations(同步…数据管家)

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
参数: state, commitObj
注意1: 在严格模式下, 不能直接让vue组件修改state里的属性值, 必须触发mutations里的方法, 来修改state里的属性值

注意2: 这里的方法, 建议由actions来触发(异步), 如果只是单一的触发(同步)可以直接利用store.commit()来提交要变更的数据

actions (异步数据管家…操作)

可以进行网络请求和一切的异步操作

  • Actions 提交的是 mutation,而不是直接变更state全局变量的值。
  • Actions 可以包含任意异步操作
第一个参数是 store对象
第二个参数是 dispatch 传递过来的值
getters(计算属性)

Vuex 允许我们在 store 中定义“getters”(可以认为是 store 的计算属性)。就像计算属性computed一样,getters 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

参数: 有个state

modules

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutations、actions、getters、甚至是嵌套子模块——从上至下进行同样方式的分割:
注意:

  1. modules 只是影响state里取值的方式
  2. state.goodsModule.xxx属性
  3. 而actions和mutations以及getter正常访问即可
export default new Vuex.Store({
  modules: {
    shopModule,
    userModule
  }
})

== vuex的核心概念到这里已经结束了,想继续深入的同学请看下文==

使用 vuex 解决跨组件通信问题

vuex 的 State 在单页应用的开发中本身具有一个“数据库”的作用,可以将组件中用到的数据存储在 State 中,并在 Action 中封装数据读写的逻辑。这时候存在一个问题,一般什么样的数据会放在 State 中呢? 目前主要有两种数据会使用 vuex 进行管理:
1、组件之间全局共享的数据
2、通过后端异步请求的数据

*即把通过后端异步请求的数据都纳入 vuex 状态管理,在 Action 中封装数据的增删改查等逻辑,这样可以一定程度上对前端的逻辑代码进行分层,使组件中的代码更多地关注页面交互与数据渲染等视图层的逻辑,而异步请求与状态数据的持久化等则交由 vuex 管理。*

下面是一个使用 vuex 管理用户数据的 demo:

// Stateconst state = {
userInfo: {}
}
// Mutaionconst mutations = {
UPDATE_USER_INFO (state, payload) {
state.userInfo = payload
}
}
// Actionexport const fetchUserInfo = async ({commit}) => {
// ... 请求用户数据
// 调用 Mutaion 写入用户数据
commit('UPDATE_USER_INFO', userInfo)
}
// Component// 在组件中引入 Action
...mapAction({
fetchUserInfoAction: `fetchUserInfo`
})
// 在 method 中调用 Action
let res = self.fetchUserInfoAction()

干货来了!!!

以下代码是vuex完整使用案例(全)

在store/index.js中

// 管理全局状态数据
// 1. 引入Vue, 和Vuex模块
import Vue from 'vue'
import Vuex from 'vuex'

// 2. 让Vue集成Vuex中间件函数
Vue.use(Vuex);

let armsModule = { // 负责管武器
  state: { // 全局变量
    goodList: [
      {
        name: "青龙刀",
        num: 0
      },
      {
        name: "丈八蛇矛",
        num: 0
      },
      {
        name: "青釭剑",
        num: 0
      },
    ] // 全局变量里的数组
  },
  mutations: { // 同步...数据管家
    buyArmsM (state, commitObj) { // 管家类型buyArmsM(随便定义), state(全局变量), commitObj(传入的参数)
      let theIndex = commitObj['index']; // 拿到索引
      state['goodList'][theIndex]['num']++; // 获取到对应的对象num++
    },
    sellArmsM (state, commitObj) { // 负责减去
      console.log(3);
      let theIndex = commitObj['index'];
      if (state['goodList'][theIndex]['num'] !== 0){
        state['goodList'][theIndex]['num']--;
      }
    }
  },
  actions: { // 异步管家(里面放异步操作)
    buyA (store, commitObj) { // store就是this.$store
      setTimeout(() => { // 异步操作
        store.commit("buyArmsM", commitObj); // 调用mutations修改数据
      }, 1000);
    }
  },
  getters: { // 全局环境上的  计算属性
    allNum (state) {
      return state['goodList'].reduce((sum, obj) => {
        return sum += obj['num'];
      }, 0);
    }
  }
};

let smokeModule = { // 负责管烟
 state: {
   arr: [
     {
       name: "中华",
       price: 45,
       num: 0
     },
     {
       name: "南京",
       price: 11,
       num: 0
     },
     {
       name: "黄鹤楼",
       price: 18,
       num: 0
     }
   ]
 },
  mutations: {
   buySmokeM (state, commitObj) {
      let theIndex = commitObj['index'];
      state['arr'][theIndex]['num']++;
   }
  }
};
// 3. 暴露Vuex的Store(数据仓库)对象
export default new Vuex.Store({
 modules: { // 配置多个Module对象
   armsModule: armsModule,
   smokeModule
 }
});

在具体的逻辑页面中:

<template>
  <div>
    <ul>
      <!--      1. 使用Vuex的变量, 可以this.$store.state 来获取 -->
      <!--      如果分了modules, 则state下要先选择Modules的名字 -->
      <li v-for="(obj, index) in this.$store.state['armsModule']['goodList']">
        <span>{{obj['name']}}</span>
        <span>{{obj['num']}}</span>
        <button @click="buy(index)">买买买</button>
      </li>
    </ul>
    <p>分支任务: </p>
    <p v-for="(obj, ind) in this.$store.state['smokeModule']['arr']" :key="ind">
      <span>{{obj['name']}}</span>
      <span>{{obj['num']}}</span>
      <span>小计: {{obj['price'] * obj['num']}}</span>
      <button @click="btn(ind)">买烟, 成年了!</button>
    </p>
  </div>
</template>

<script>
  export default {
    name: 'Home',
    methods: {
      buy(ind) {
        this.$store.commit("buyArmsM", {index: ind}); // commit() 用于触发mutations的函数执行
        // 参数1: 要执行的类型, 参数2: 要传递的参数
      },
      btn (ind) {
        this.$store.commit("buySmokeM", {index: ind});
      }
    }
  }
</script>

<style scoped>

</style>

注意

  • 使用vuex的变量:this.$store.state来获取
  • his.$store.commit中commit() 用于触发mutations的函数执行

如果看了以上文章,你还没有明白,来找我,捶死我!

你可能感兴趣的:(vuex详解及入门案例)