5

第一章 初识vuex

vuex有什么用?

比如, vue做了一个音乐app, 里面的播放组件, 这组件应该是在所有的页面都有用到的.
希望在所有的页面都能控制播放器的 暂停/播放, 或者说都可以选择是否 随便播放/单曲循环.
这就涉及到了多组件之间的传参,而且是非常复杂的传参.这时候使用vuex是合适的.

vuex是什么?

通过简单的描述, 我们大概可以理解为vuex是一个公共 状态库 , 你可以在所有的组件里面去使用,修改

那这个状态库是由什么组成的?

一. state: 最最基本的状态

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

二. getters: 相当于计算属性

当我们得到state的值之后, 使用getters, 将这些基本的值进行组合加工, 得到我们需要的值

三. mutations:

他的作用就是来改变state的值, 并且是唯一的方法

四. actions:

假如你有好几个mutation需要提交, 一个一个的写就太傻逼了. 可以用 actions 来封装 mutations. 

☆☆☆☆☆☆☆☆☆☆☆暂且完结☆☆☆☆☆☆☆☆☆☆☆☆☆

第二章 vuex核心概念详解

1. state的运用

a. 最简单的方法就是在计算属性中返回state状态

// 创建一个 Counter 组件
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

b. 我们用vue-cli来制作webapp的时候

import store from './store'
const app = new Vue({
  el: '#app',
  // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
  store
})

// 然后就可以在组件中
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

c. 若一个组件需要很多的state状态的话, 上面方式就不够简洁了. 使用 mapState 辅助函数


computed: mapState({
  // 箭头函数可使代码更简练
  count: state => state.count,

  // 传字符串参数 'count' 等同于 `state => state.count`
  countAlias: 'count',

  // 为了能够使用 `this` 获取局部状态,必须使用常规函数
  countPlusLocalState (state) {
    return state.count + this.localCount
  }
})

2. getters的运用

a. 基本使用

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)
    }
  }
})

// 在组件中使用它
computed: {
  doneTodosCount () {
    return this.$store.getters.doneTodosCount
  }
}

b. mapGetters 辅助函数 简化应用

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
    ...mapGetters([
      'doneTodosCount'
      // ...
      // 设置别名 ,使用对象形式:
      // doneCount: 'doneTodosCount'
    ])
  }
}

3. mutations的运用

a. mutations 下面是一个简单的例子

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

// 调用mutations的方法
store.commit('increment')

b. 给mutations 提交额外的参数

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

// 一般载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit('increment', {amount: 10})
// 或者用对象的方式提交
store.commit({
  type: 'increment',
  amount: 10
})

c. 使用常量替代 Mutation 事件类型

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'

const store = new Vuex.Store({
  // ...
  mutations: {
    // 假如不用常量, 如 'some-mutations' , 可能会造成格式上的错乱
    [SOME_MUTATION] (state) {
      // ...
    }
  }
})

d. 在组件中提交 Mutations

// 方法1
this.$store.commit('xxx')
// 方法2 使用 mapMutations 
import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapMutations([
      'increment' // 映射 this.increment() 为 this.$store.commit('increment')
    ]),
    ...mapMutations({
      add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
    })
  }
}

□□□□□□□□□□□□□综合实例□□□□□□□□□□□□

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    [SOME_MUTATION] (state, n) {
      state.count += n
    }
  }
})
import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapMutations([
      // 映射 this.increment() 为 this.$store.commit('increment')
      increment: 'SOME_MUTATION'
    ]),
    
    // 调用上面映射的方法 并且把参数n传进去
    this.increment(1)
  }
}

4. actions的运用

a. 前面我们已经说过了,actions主要是来同时提交多个mutations

// mutations.js
import * as types from './mutation-types'
const mutations = {
  [types.sx](state, a){
    state.a = a    
  },
  [types.sb](state, b){
    state.b = b    
  }...
}
// actions.js
// 我们需要同时更改state的a,b的值
import * as types from './mutation-types'
export const selectPlay = function ({commit, state}, a, b) {
  commit(types.sx, a)
  commit(types.sb, b)...
}

b. 进行异步操作 多看看 这例子写的很好

actions: {
  checkout ({ commit, state }, products) {
    // 把当前购物车的物品备份起来
    const savedCartItems = [...state.cart.added]
    // 发出结账请求,然后乐观地清空购物车
    commit(types.CHECKOUT_REQUEST)
    // 购物 API 接受一个成功回调和一个失败回调
    shop.buyProducts(
      products,
      // 成功操作
      () => commit(types.CHECKOUT_SUCCESS),
      // 失败操作
      () => commit(types.CHECKOUT_FAILURE, savedCartItems)
    )
  }
}

c. 在组件中分发 Action

// 原始方法 如提交上面的购物车
this.$store.dispatch('checkout ')
// 使用 mapActions
import { mapActions } from 'vuex'
export default {
  // ...
  methods: {
    ...mapActions([
      'increment' // 映射 this.increment() 为 this.$store.dispatch('increment')
    ]),
    ...mapActions({
      add: 'increment' // 映射 this.add() 为 this.$store.dispatch('increment')
    })
  }
}

☆☆☆☆☆☆☆☆☆☆☆暂且完结☆☆☆☆☆☆☆☆☆☆☆☆☆

第三章 项目结构

图片描述

这是vue-cli构建的一个项目, store就是存放vuex的文件夹

import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import * as getters from './getters'
import state from './state'
import mutations from './mutations'

// 插件的运用, 它能监控state的值
import createLogger from 'vuex/dist/logger'

Vue.use(Vuex)

// 但是, 这会耗性能, 所有判断线上线下打包模式, 从而决定是否使用
const debug = process.env.NODE_ENV !== 'production'

export default new Vuex.Store({
  actions,
  getters,
  state,
  mutations,
  strict: debug,
  plugins: debug ? [createLogger()] : []
})

荆棘鸟
398 声望4 粉丝