vuex 理解与应用

第一章 初识vuex

vuex有什么用?

好比, vue作了一个音乐app, 里面的播放组件, 这组件应该是在全部的页面都有用到的.
但愿在全部的页面都能控制播放器的 暂停/播放, 或者说均可以选择是否 随便播放/单曲循环.
这就涉及到了多组件之间的传参,并且是很是复杂的传参.这时候使用vuex是合适的.vue

vuex是什么?

经过简单的描述, 咱们大概能够理解为vuex是一个公共 状态库 , 你能够在全部的组件里面去使用,修改web

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

一. state: 最最基本的状态vuex

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

二. getters: 至关于计算属性vue-cli

当咱们获得state的值以后, 使用getters, 将这些基本的值进行组合加工, 获得咱们须要的值

三. mutations: app

他的做用就是来改变state的值, 而且是惟一的方法

四. actions: webapp

假如你有好几个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. 基本使用this

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()] : []
})
相关文章
相关标签/搜索