Vue状态管理之vuex

发布时间:2019-08-20 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了Vue状态管理之vuex脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

初步认识Vuex
1)Vuex是一个专为Vue.js应用程序开发的转态管理模式;集中存储和管理应用的所有组件状态。
2)使用场景:
处理多组件依赖于同一个数据
一个组件的行为——改变数据——影响另一个组件的视图(共用依赖的数据)
Vuex将组件公用数据抽离,在一个公共仓库管理,使得各个组件容易获取(getter)数据,也容易设置数据(setter)。

Vuex之Store
1)Store类就是在存储数据和管理数据方法的仓库,实现方式就是将数据和方法以对象形式传入其实例中。要注意一个应用或项目中只能存在一个Store实例。

sate
用来存放组件之间共享的数据

mutations(只能处理同步函数)
改变状态(state)的唯一方式是通过提交(commIT)一个mutation

getters
对state的数据进行筛选,过滤

actions(可以包含任意异步操作,ajax、setTimeoutsetInterval

https://vuex.vuejs.org/zh/ins...

1)安装

npm install vuex --save
或
yarn add vuex

在一个模块化的打包系统中,您必须显示地通过Vue.use()来安装Vuex:

import Vue From 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

当使用全局script标签引用Vuex时,不需要以上安装过程

Vuex依赖Promise(不支持PRomise的浏览器)

<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>

npm install es6-promise --save # npm
yarn add es6-promise # Yarn
import 'es6-promise/auto'

2)State
Vuex使用单一状态树,用一个对象包含了全部的应用层级状态。这也意味着,每个应用将仅仅包含一个store实例。(由于 store 中的状态是响应式的,在组件中调用 store 中的状态简单到仅需要在计算属性(computed)中返回即可。)
在Vue组件中获得Vuex状态
最简单的方法是在计算属性中返回某个状态

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

然而,这种模式导致组件依赖全局状态单例。在模块化的构建系统中,在每个需要使用 state 的组件中需要频繁地导入,并且在测试组件时需要模拟状态。

Vue通过store选项,提供了一种机制将状态从根组件“注入”到每个子组件中(需要调用Vue.use(Vuex))

const app = new Vue({
  el: '#app',
  // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

mapState辅助函数

// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'

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

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

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

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

对象展开运算符(mapState函数返回的是一个对象)

computed: {
  localComputed () { /* ... */ },
  // 使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    // ...
  })
}

3)Getter
Vuex允许我们在store中定义“getter”(可以认为是store的计算属性)。就像是计算属性一样,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。(一般用于派生状态)
Getter接受state做为其第一个参数:

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

Getter会暴露store.getters对象,可以以属性的形式访问这些值:

getters: {
  // ...
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]

注意,getter 在通过属性访问时是作为 Vue 的响应式系统的一部分缓存其中的。

你也可以通过让 getter 返回一个函数,来实现给 getter 传参。在你对 store 里的数组进行查询时非常有用。

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

mapGetters辅助函数
mapGetters辅助函数仅仅是将store中的getter映射到局部计算属性:

import { mapGetters } from 'vuex'

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

如果你想将一个getter属性另取一个名字,使用对象形式

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

4)Mutation
更改Vuex的store中的状态的唯一方法是提交mutation。Vuex中的mutation非常类似于事件:每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受state作为第一个参数:

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

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

store.commit('increment')

你可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload):

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

提交mutation的另一种方式是直接使用包含type属性的对象

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

mutation必须是同步函数

5)Action
Action类似于mutation,不同在于:
Action提交的是mutation,而不是直接变更状态。
Action可以包含任意异步操作

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。

Action通过store.dispatch方法触发:

store.dispatch('increment')

我们可以在 action 内部执行异步操作:

actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}

Actions 支持同样的载荷方式和对象方式进行分发:
// 以载荷形式分发
store.dispatch('incrementAsync', {
  amount: 10
})

// 以对象形式分发
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise:

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}
store.dispatch('actionA').then(() => {
  // ...
})

6)Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

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

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

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

对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象。

const moduleA = {
  state: { count: 0 },
  mutations: {
    increment (state) {
      // 这里的 `state` 对象是模块的局部状态
      state.count++
    }
  },

  getters: {
    doubleCount (state) {
      return state.count * 2
    }
  }
}

同样,对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState:

const moduleA = {
  // ...
  actions: {
    incrementIfOddOnRootSum ({ state, commit, rootState }) {
      if ((state.count + rootState.count) % 2 === 1) {
        commit('increment')
      }
    }
  }
}

对于模块内部的 getter,根节点状态会作为第三个参数暴露出来:

const moduleA = {
  // ...
  getters: {
    sumWithrootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}

默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。

项目结构
├── index.htML
├── main.js
├── api
│   └── ... # 抽取出API请求
├── components
│   ├── App.vue
│   └── ...
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块

交流与学习QQ:759020213

脚本宝典总结

以上是脚本宝典为你收集整理的Vue状态管理之vuex全部内容,希望文章能够帮你解决Vue状态管理之vuex所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。