Vuex 5大核心内容详解

vuex 状态管理

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

状态管理模式

new Vue({
  //state: 驱动应用的数据源
  data () {
    return {
      count: 0
    }
  },
  //view: 以声明方式将state映射到视图
  template: `<div>{{count}}</div>`,
  //actions:响应在view上的用户输入导致的状态变化
  methods: {
    countAdd () {
      return count++;
    }
  }
})

在小型的项目中,可以用一个简单的store模式,若用vuex反而显得繁琐。大型项目用vuex就是很好的选择了
单向数据流图示:
在这里插入图片描述

vuex在于解决:多个视图组件依赖同一状态,来自不同的视图的行为需要改变同一个状态,然而兄弟组件的状态传递不能实现,父子组件传参又相对繁琐。嵌套组件,状态维护困难
vuex作用

  • 提取共享状态,以全局单例模式管理
  • 定义和隔离状态管理中的各种概念,并通过强制规则维持视图和状态间的独立性
  • 代码结构化,易于管理和维护
    vuex图示
    在这里插入图片描述

vuex引入

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(vuex) 

State —单一状态树

单一状态树(state):唯一的数据源。意味着每个应用将仅仅包含一个store实例
全局状态单例
在组件的computed计算属性中可以直接计算state,一般是直接返回store.state.count
模块化的构建中
需要在根组件中注入store选项,每个子组件就可以通过this.$store.state.count访问状态

辅助函数 mapSate

mapState函数帮助我们当组件需要获取多个状态时,统一生成计算属性。(单个生成计算属性太繁杂)

import { mapState } from 'vuex'

export default {
  data () {
    return {
      localCount: 0
    }
  }
  //'''
  computed: mapSate({
    // 箭头函数可使代码更简练
    count: state => state.count,

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

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

因为计算属性的名称和state的子节点名称相同,ES6语法,参数也可以是字符串数组

computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])

对象展开运算符(ES6语法)

目的:将mapState返回的对象与局部计算属性混合使用,最终将对象传给computed属性

computed: {
  localComputed () {
    //局部计算属性的操作
    return localCount++
  },
  ...mapState([
    'count'
  ])
}

PS:不需要把所有的状态都放入vuex,不然代码管理反而冗杂,组件自己独有的状态可以放入自己的组件内部作为局部状态

Getter —store的计算属性

Getter可以认为是store的计算属性,getter的返回值会根据它的依赖被缓存起来,且只有它的依赖值发生了变化才会被重新计算

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

PS:getter参数:

  • 第一个参数为state对象,可接受其他getter作为第二个参数
getters: {
  //...
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}

通过属性访问

store.getters.doneTodosCount
//或者this.$store.getters.doneTodosCount

通过方法访问

通过让getter返回一个函数,来实现给getter传参。(数组或对象查询很有用)

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

辅助函数 —mapGetters

将store中的getter映射到局部计算属性

import { mapGetters } from 'vuex'

export default {
  //...
  computed: {
    ...mapGetters([
      'doneTodos'  //ES6 语法,同名属性的简写,当然也可以重命名其他名字
    ])
  }
}

Mutation —改变(类似于事件)

  • 改变Vuex中的store中的state的唯一方法就是提交mutation
  • 每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler),这个回调函数就是我们实际进行状态变更的地方。并且它会接受state作为第一个参数:
const store = new Vuex.Store({
  state: {
    count: 4
  },
  mutations: {
    countAdd (state) {
      //变更状态
      state.count++
    }
  }
})

提交mutation
你不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 countAdd 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:

store.commit('countAdd')

提交载荷(Payload)—mutation额外的参数

  • 载荷即,mutation其他参数
  • 一般情况下,Payload以对象形式传参,可以包含多个字段并记录Mutation
  • 在提交时可以是对象乡试提交
mutations: {
  countAdd: (state,Payload) {
    state.count += Payload.acount
  }
}

提交方式:

//一般提交方式,只当第二个参数为载荷Payload
store.commit('countAdd',{
  acount: 10
})

//对象提交方式,把type也当作载荷Payload
store.commit({
  type: 'countAdd',
  acount: 10
})

在组件中提交mutation

import { mapMutations } from 'vuex'

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

mutation必须是同步函数
原因很简单,我们的mutations是改变状态的,那么状态一改变就应当更新相应组件。而异步函数中状态的改变是不可追踪的,我们不知道什么时候状态发生了变化。所以mutations中不允许异步函数。为了解决这一问题,出现了action

Action

  • Action提交的是mutation,而不是直接变更状态
  • Action可以包含任意异步操作
  • Action接受一个与store实例具有相同方法和属性的context对象。可以调用context.commit提交一个mutation,和通过context.statecontext.getters来获取stategetters
  • Action通过store.dispatch方法分发
  • Action和mutations一样支持载荷和对对象形式分发

在组件中分发Action

import { mapAction } from 'vuex'

export default {
  // ...
  methods: {
    ...mapAction([
      'countAdd', // 将 `this.countAdd()` 映射为 `this.$store.dispatch('countAdd')`
    ]),
    ...mapAction({
      add: 'countAdd' // 将 `this.add()` 映射为 `this.$store.dispatch('countAdd')`
    })
  }
}

组合Action —用到promise和async/await实现

  • store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise
  • store.dispatch 仍旧返回 Promise
  • 利用async/await实现Action组合
// 假设 getData() 和 getOtherData() 返回的是 Promise
actions: {
  async actionA ({ commit }) {
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
}

Module

Veux允许我们将store分割成模块(module)。每个模块(module)拥有自己的state,mutation,action,getter。甚至嵌套子模块

const moduleA = {
  state: { ... },
  //参数增加
  //参数(state,Payload)
  mutations: { ... },
  //参数({state,context,rootState})
  actions: { ... },
  //参数(state,getters,rootState)
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  state: { ... },
  getters: { ... },
  actions: { ... },
  mutations: { ... }
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

PS:模块这一节涉及到的东西较多,参考官网Vuex模块(modules)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DiuDiu_yang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值