# VueX 学习

# 基本概述

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

# 单向数据流理念

典型通讯方式:父子组件通讯、兄弟组件通讯

state通过声明的方式将数据映射到view中,view拿到数据进行渲染,用户在view层更新数据,view将 更改的数据传递到actions中,actions拿到数据在去状态中更新state。

# 核心概念

在vuex中store是整个应用的核心,“store”属于容器的存在,包含着大部分state状态,为控制store的 途径唯一性,改变状态只能通过mutation来改变。

# State

1、获取vuex中state状态值

this.$store.state.值名称

2、mapState 辅助函数
当一个组件需要获取多个状态时,mapState可自动生成计算属性

import {mapState} from 'vuex'
export default {
 name: 'home',
 computed: mapState(['nickname','age','gender'])
}

上面代码相当于

nickname(){return this.$store.state.nickname}
age(){return this.$store.state.age}
gender(){return this.$store.state.gender}

如果在计算属性(computed)中需要自定义一个计算属性,将使用下面的方法

computed: {   //computed是不能传参数的
  value(){
   return this.val/7
},
// 使用ES6的扩展运算符
  ...mapState(['nickname','age','gender'])
}

# Getter

可以将其看作store的计算属性,就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
在getter中有两个参数,第一个参数代表当前状态中的state,第二个参数代表getters本身。

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    },
    doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
  }
})

使用方法的方式访问getters

getters: { 
  getTodoById: (state) => (id) => {
    return state.todos.find(todo => todo.id === id)
  }
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }

mapGetters辅助函数

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
  // 使用对象展开运算符将 getter 混入 computed 对象中
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}

如果你需要在mapGetters中更改属性名称,需要使用对象的形式

...mapGetters({
  // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
  doneCount: 'doneTodosCount'
})

# mutation

基本定义
在vuex中mutation类似于一个事件,它存在一个事件类型和一个回调函数,回调函数就是我们实际修改state的地方。
在mutation中我们不能直接调取回调函数,必须先注册事件。

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    // increment=事件类型(注册事件)
    increment (state) {
      // 变更状态
      // 注意在所有的mutation中,更改的状态都必须在state先声明才能使用。
      state.count++
    }
  }
})

载荷
在mutation中如果你想使用store.commit传入额外的参数,就要使用载荷(payload)。 但是在载荷中我们一般传递的都是对象,因为对象的表意更加的明确。

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit('increment', {
  amount: 10
})

既然 Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:
1、在 store 中初始化好所有所需属性。
2、当需要在对象上添加新属性时,使用 Vue.set(obj, 'newProp', 123),
3、或者利用对象展开运算符我们可以这样写:

state.obj = { ...state.obj, newProp: 123 }