Vuex官方文档笔记

每个Vuex应用的核心就是store(仓库)。store本质是一个容器,它包含着你的应用中大部分的状态(state)。Vuex和单纯的全局对象有以下两点不同:

1、Vuex的状态存储是响应式的。当Vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件会相应地得到高效更新。

2、不能直接改变store中的状态,改变store中状态的唯一途径是显示的提交(commit)mutation。

为了在Vue组件中访问this.$store属性,需要为Vue实例提供创建好的store。Vuex提供了一个从根组件向所有子组件以store选项的方式注入该store的机制。通过在根实例中注册store选项,该store实例会注入到根组件下的所有子组件中,且子组件能通过this.$store访问到。

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
  state:{...},
  mutations:{各个方法对state中数据的改动}
})
new Vue({
	el: '#app',
	store //ES6语法
})

State 单一状态树

Vuex使用单一状态树,用一个对象就包含了全部的应用层级状态。它作为唯一数据源而存在。每个应用将仅仅包含一个store实例。单状态树和模块化并不冲突

由于Vuex的状态存储是响应式的,从store实例中读取状态最简单的方法就是在计算属性(computed)中返回某个状态。当状态发生变化,会重新求取计算属性,并且触发更新相关联的DOM。

使用对象展开运算符(…)和mapState辅助函数可以将需要的状态从store中提取出来使用。

Getter

Vuex允许我们在store中定义"getter"(类似computed属性),像计算属性一样,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了变化才会被重新计算。

Getter接收state作为其第一个参数。Getter会暴露为store.getters对象,可以以属性的形式访问下面的方法获取值。Getter也可以接受其他getter作为第二个参数。

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

**可以通过让getter返回一个函数来实现给getter传参。**getter在通过方法访问时,每次都会去进行调用而不会缓存结果。

mapGetter辅助函数将store中的getter映射到局部计算属性。

const store = new Vuex.Store({
  getters:{
    func1:state=>{return ...},
    func2:(state,getters) =>{return ...},
    func3:(state) =>(id) =>{retrun ...}
  }
})
import {mapGetters} from 'vuex'
...mapGetters(['func1','func2'])
...mapGetters({
  newNmae:'func1' //将一个getter属性另取一个名字
})                  

Mutation

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

方法接收state作为第一个参数,同时可以添加其他需要的参数(大多数情况下是个对象)。(Payload 载荷)

对象风格的提交方式
store.commit({
	type:'funcname',
	....
}) 
store.commit('funcname',{...})

使用常量替代mutation事件类型在各种Flux实现中是很常见的模式。

const SOME_MUTATION = 'SOME_MUTATION'
const store = Vuex.Store({
  mutations:{
    //ES6风格的计算属性命名功能来使用一个常量作为函数名
    [SOME_MUTATION](state){}
  }
})
可以在组件中使用this.$store.commit('xxx')方式提交mutation,或者使用mapMutations辅助函数将组件中的methods映射为store.commit(需要在根节点注入store)
methods:{
  ...mapMutations(['name1','name2'])
  ...mapMutations({
  		newName:'name1'
		})
}

**mutation必须是同步函数!!!!!**在Vuex中,mutation都是同步事务。

Action

Action类似于mutation,不同在于:

  • Action提交的是mutation,而不是直接变更状态
  • Action可以包含任何异步操作。(这个才是重点)

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

mutations:{
  funcname(state){
    
  }
},
actions:{
  funcname (context){
    context.commit('...')
  },
  //通过解构来简化代码
  funcname2 ({commit}){
    commit('...')
  }
}

Action通过store.dispatch方法触发

store.dispatch('...')

mutation是同步执行,我们通过actions可以在其内部执行异步操作。异步操作的结果通过提交mutation来进行状态变更。

Actions同mutations一样同样支持载荷方式(Payload)和对象方式进行分发。

//载荷方式
store.dispatch('...',{})
//对象方式
store.dispatch({type:'...',...})

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

Action通常是异步的,在异步操作的时候通过Promise来处理复杂的异步流程。store.dispatch返回的是Promise。

methods:{
  ...mapActions(['...','...']),
  ...mapActions({
    funcname:'actions.funcname' //alias 别名
  })
}


actions:{
	actionB ({dispatch,commit}){
    return dispatch('actionA').then(() =>{
			commit('MutationOperation')
    })
  }
}
利用async/await组合action:
actions:{
  async actionA({commit}){
    commit('gotData',await getData())
  },
  async actionB({dispatch,commit}){
		await dispatch('actionA')
    commit('gotOtherData',await getOtherData())
  }
}

Module

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

对于模块内部的mutation和getter,接收的第一个参数是模块的局部状态对象state。对于模块内部的action,局部状态通过context.state暴露出来,根节点状态则为context.rootState。对于模块内部的getter,根节点状态会作为第三参数暴露出来。

**默认情况下,模块内部的action、mutation和getter是注册在全局命名空间的,这样使得多个模块能够对同一mutation或action作出响应。**如果希望你的模块具有更高的封装性和复用性,你可以通过添加namespaced:true的方式使其成为带命名空间的模块。当模块注册后,它的所有getter、action、mutation都会自动根据模块注册的路径调整命名。

在带命名空间的模块内访问全局内容(Global Assets)

如果你希望使用全局state和getter,rootState和rootGetters会作为第三和第四参数传入getter,也会通过context对象的属性传入action。若需要在全局命名空间内分发action或提交mutation,将{root:true}作为第三参数传给dispatch或commit即可。

在带命名空间的模块注册全局action

若需要在带命名空间的模块注册全局action,你可以添加root:true,并将这个action的定义放到函数handler中:

{
  actions:{
    someAction:{
      root:true,
      handler (namespaceedContext,payload){...} ->someAction
    }
  }
}
带命名空间的绑定函数

在使用mapState,mapGetters,mapActions和mapMutations这些函数来绑定带命名空间的模块时,写起来可能比较繁琐,可以将模块的空间名称字符串作为第一个参数传递给函数,这样所有绑定都会自动将该模块作为上下文。

computed: {
  ...mapState('some/nested/module', {
    a: state => state.a,
    b: state => state.b
  })
},
methods: {
  ...mapActions('some/nested/module', [
    'foo', // -> this.foo()
    'bar' // -> this.bar()
  ])
}

另外,可以通过使用createNamespaceHelpers创建基于某个命名空间辅助函数,它返回一个对象,对象里有新的绑定在给定命名空间值上的组件绑定辅助函数。

import {createNamespacedHelpers} from 'vuex'
const {mapState,mapActions} = createNamespacedHelers('modulename')
computed:{
  ...mapState({
    a: state => state.a,
    b: state => state.b
  })
}
模块动态注册

在store创建之后,可以使用store.registerModule方法注册模块。

store.registerModule('modulename',{...})
store.registerModule(['nested','modulename'].{...}) //注册嵌套模块

使用store.unregisterModule(modulename)来动态卸载模块。不能通过此方法卸载静态模块(即创建store时声明的模块)。 store.hasModule(modulename)检查模块是否已经被注册到store。

使用函数来声明模块状态

state: ()  => ({....})

项目结构

Vuex并不限制你的代码结构,但是,它规定了一些需要遵守的规则:

1、应用层级的状态应该集中到单个store对象中。

2、提交mutation是更改状态的唯一方法,并且这个过程是同步的。

3、异步逻辑都应该封装到action里面。

遵从上面的规则,你可以随意组织代码规则,如果store文件过大,只需将action、mutation和getter分割到单独的文件。

插件

Vuex的store接受plugins选项,这个选项暴露出每次mutation的钩子。Vuex插件就是一个函数,它接收store作为唯一参数。

const myPlugin = store =>{
  store.subscribe((mutation,state) =>{
    ...//每次mutation之后调用
  })
}
const store = new Vuex.Store({
	plugins:[myPlugin]                  
})                  

在插件中不允许直接修改状态,类似于组件,只能通过提交mutation来触发改变。通过提交mutation,插件可以用来同步数据源到store。

开启严格模式,只需要在创建store的时候传入strict: true。在严格模式下,无论何时发生了状态变更且不是由mutation函数引起的,都将抛出错误。严格模式使用在开发环境中。

热重载

https://vuex.vuejs.org/zh/guide/hot-reload.html

API参考

Vuex.Store 构造器选项

state:Vuex store实例的根state对象。使用一个返回对象的函数,返回的对象作为根state,重用。
mutations:处理函数总是接受state作为第一个参数(如果定义在模块中,则为模块的局部状态),payload作为第二个参数(可选)。
actions:处理函数总是接受context(一个类store对象)作为第一个参数,payload作为第二个参数(可选)。context对象有以下属性:
{
	state,      // 等同于 `store.state`,若在模块中则为局部状态
  rootState,  // 等同于 `store.state`,只存在于模块中
  commit,     // 等同于 `store.commit`
  dispatch,   // 等同于 `store.dispatch`
  getters,    // 等同于 `store.getters`
  rootGetters // 等同于 `store.getters`,只存在于模块中
}
getters:在store上注册时,getter接受以下参数:
  state, 
  getters, //等同于store.getters
定义在一个模块中时有以下参数:
state ,//在模块中定义则为模块的局部状态
getters, //等同于store.getters
rootState, // 等同于store.state
rootGetters  //所有getters

modules:包含了子模块的对象,会被合并到store中。模块的状态使用key关联到store的根状态。模块的mutation和getter只会接收module的局部状态(state)作为第一个参数,而不是根状态,并且模块action的context.state同样指向局部状态。
{
  key: {
    state,
    namespaced?,
    mutations,
    actions?,
    getters?,
    modules?
  },
  ...
}
plugins:一个数组,包含应用在store上的插件方法。这些插件直接接收store作为唯一参数,可以监听mutation或者提交mutation。
strict: Vuex store严格模式,在严格模式下,任何mutation=处理函数以外修改Vuex state都会抛出错误。
devtools:为某个特定的Vuex实例打开或关闭devtools。关闭则不会订阅到devtools插件。


Vuex.Store 实例属性

  • state 根状态 只读
  • getter 暴露出注册的getter 只读

Vuex.Store 实例方法

commit : 提交mutation 。root:true允许在命名空间模块里提交根mutation

dispatch: 分发action。root:true 允许在命名空间模块里分发根的action。返回一个解析所有被触发的action处理器的Promise。

replaceState/watch

subscribe:订阅store的mutation 。 handler会在每个mutation完成后调用,接收mutation和经过mutation后的状态作为参数。

subscribeAction:订阅store的action。handler会在每个action分发的时候调用并接收action描述和当前的store的state这两个参数。3.1.0后,可以指定subscribeAction订阅函数调用的时机是在action之前还是之后

store.subscribeAction({
  before:(action,state) =>{...},
  after:(action,state) =>{...}
})

registerModule:注册一个动态模块。

unregisterModule:卸载一个动态模块。

hasModule:检查一个模块的名称是否已经被注册。

hotUpdate: 热替换芯的action和mutation。

组件绑定的辅助函数

mapState:为组件创建计算属性以返回Vuex store中的状态。

mapGetters: 为组件创建计算属性以返回getter的返回值。

mapActions:创建组件方法分发action。

mapMutations:创建组件方法提交mutation。

createNamespacedHelpers:创建基于命名空间的组件绑定辅助函数。其返回一个包含mapState,mapGetters,mapActions,mapMutations的对象。绑定在给定的命名空间上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值