Vuex学习笔记

 

一、安装

1.直接下载 / CDN 引用

https://unpkg.com/vuex

Unpkg.com 提供了基于 NPM 的 CDN 链接。以上的链接会一直指向 NPM 上发布的最新版本。您也可以通过 https://unpkg.com/[email protected] 这样的方式指定特定的版本。

在 Vue 之后引入 vuex 会进行自动安装:


2.npm安装:

npm install vuex --save

3.Yarn:

yarn add vuex

二、理解vuex 

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

1.为什么会有vuex?

首先我们从我常用的每个组件中的data保存数据的模式开始说起。

 

                                                        Vuex学习笔记_第1张图片

这是一个单向数据流的状态管理模式:

  • state,驱动应用的数据源;
  • view,以声明方式将 state 映射到视图;
  • actions,响应在 view 上的用户输入导致的状态变化。

这模式在一个组件或者父子组件中是没有问题的,但是当我们遇到多个组件要共享一个状态时,单向数据流的简洁性很容易被破坏:

  • 多个视图依赖于同一状态。
  • 来自不同视图的行为需要变更同一状态。

 因此,我们把组件的共享状态抽取出来,以一个全局单例模式管理,就相当于一个大的仓库,这个应用下的所有组件都可以按照vuex定义的规则存储状态(这里不叫做数据,只能叫做状态合适,因为当你刷新浏览器时所有状态是会重置的),而每个组件中的data就相当于每个的小仓库,这里只管理该组件的状态就好了。这样一个应用的数据状态管理就非常有条理,不会混乱。

三、理解vuex的五个核心概念:State、Getter、Mutation、Action、Module

Module(为了防止这个store仓库臃肿而划分的具体子模块):

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

const numbers = {
	state:{
		account:'sd '
	},
	mutations:{
		ADD_NUMBER:(state,account)=>{
			state.account=account
			console.log('触发mutations')
		}
	},
	actions:{
		addnumber({commit},numbers){
			setTimeout(() => {
		      const accounts= numbers + 10
			  console.log('触发actions')
			  commit('ADD_NUMBER', accounts)
		    }, 1000)
		}
	}
}
export default numbers

我们先讲module是因为我们要讲两种使用vuex的方式,这两种方式就是使用module模块划分和不使用module模块划分

上面这种就是使用module模块划分的方式,我们来看下使用模块划分的文件结构目录(当然也可以按照自己的想法来划分项目结构):

                                                       Vuex学习笔记_第2张图片

这种方式就是每个模块都添加到modules文件夹中,像number.js一样,getter.js写每个模块的计算属性,index.js引入每个模块,State:

state就像是组件中的data一样,里面定义的是具体的参数,例如index.js中的state:

index.js:

import Vue from 'vue'
import Vuex from 'vuex'
import numbers from './modules/number'
import getters from './getters'
Vue.use(Vuex)
const store = new Vuex.Store({
	modules:{
		numbers
	},
state:{
		account:'sd '
	},
	mutations:{
		ADD_NUMBER:(state,account)=>{
			state.account=account
			console.log('触发mutations')
		}
	},
	actions:{
		addnumber({commit},numbers){
			setTimeout(() => {
		      const accounts= numbers + 10
			  console.log('触发actions')
			  commit('ADD_NUMBER', accounts)
		    }, 1000)
		}
	},
	getters
})
export default store

 获取state中状态的方式:

1.main.js中全局引入:

import store from './store' // 全局引入
new Vue({
  el: '#app',
  i18n,
  router,
  store,  // 状态从根组件“注入”
  components: { App },
  template: ''
})

 当全局引入时,分modules和不分module(直接在store中定义所有的mutation,action)的获取方式又是不一样的,子组件中使用:全局引入时可以在子组件中使用this.$store.state获取state的状态,

不划分模块:this.$store.state.account获取,

划分模块,要写上模块名:this.$store.state.numbers .account获取,若写成this.$store.state.account会报undefined

2.组件中局部引入:import store from '@/store'

局部引入时每个组件都需要引入,有点麻烦。这种方式可以用:store.state获取

不划分模块:store.state.account获取

划分模块,要写上模块名:store.state.numbers .account获取,若写成store.state.account会报undefined

mapState 辅助函数

当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 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
    }
  })
}

Getter:

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

const getters = {
  account: state => state.numbers.account // 接受state作为第一个参数

}
export default getters

mapGetters 辅助函数:

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

import { mapGetters } from 'vuex'

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

 Mutation:

更改vuex中的状态的唯一方法是提交mutation,如:commit('ADD_NUMBER', accounts),他接受state作为第一个参数,还可以接受其他传入的参数作为载荷(payload)

注意:mutation中只能写同步函数

 

在组件中提交 Mutation

你可以在组件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。 

import { mapMutations } from 'vuex'

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

      // `mapMutations` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
    ]),
    ...mapMutations({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
    })
  }
}

Action:

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。例如你可以在action写调用接口,延时器,而不可以在mutation中写
  • 在组件中提交action,利用dispatch触发(同样的用this.$store.state还是store.state取决于全局玉如还是局部引入),提交的第一个参数为action函数名称,第二个参数为传入的参数:
 btnclick(){
      	var that = this
      	console.log(that.$store.state.account)
      	this.$store.dispatch('addnumber',that.numbers).then(res =>{
//    		console.log(that.$store.state.account)
      	})
      }

组件:





 

在组件中分发 Action

你在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store):

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
   ...mapActions({
	      btnclick: 'addnumber' // 将 `this.btnclick()` 映射为 `this.$store.dispatch('addnumber')`
	    })
  }
}

 mapActions映射的意思就是当正常写法我们需要绑定一个点击事件btnclick,然后this.$store.dispatch触发action事件,而用了映射则直接像上面的写法即可,少写了this.$store.dispatch触发action事件

你可能感兴趣的:(vue,vuex)