avatar

Catalog
vuex

vuex工作流程

Snipaste_2020-02-15_13-14-08

Store

store是一个仓库,里面包含了state,mutation,actions,创建完仓库我们要把挂载到根组件中,这样可以确保,所有的子组件都可以访问到vuex中的数据,通过(this.$store)

javascript
//根组件
let app = new Vue({
store,
})
javascript
//store仓库
let store = new Vuex.Store({
state:{
total: 0,
goods: [
{title: 'iphone',price: 3000,num: 4},
{title: 'mi',price: 4000,num: 2}
]
}
})

State

state你可以理解为是我们仓库中存放数据的地方,那么组件该如何获取state中的数据呢?

javascript

computed: {
totalPrice: this.$store.state.total
}
// 这里为什么要用计算属性呢,是因为如果vuex中的数据发生了变换,对应的页面也会适应更新

Getter

有时候我们需要从store中的state来改变一些新的状态,例如过滤。类似计算属性

javascript
computed:{
totalPrice(){
return this.$store.state.goods.filter(item => {
item.price > 10000
})
}
}

如果你有许多个组件都需要使用这个函数,那么你必须在每个组件中把这段代码复制过去。

vuex中允许我们在store中定义getter属性,可以认为是store的计算属性。返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

getters接受第一个参数为state,第二个参数为getters

javascript
let store = new Vuex.Store({
state: {
total: 0,
goods: [
{title: 'iphone',price: 3000,num: 4},
{title: 'mi',price: 4000,num: 2}
]
},
getters: {
handle: state=>{
return state.goods.filter(item=>item.price > 300)
}
//和上面相同,这个是es6的写法
handle(state){
return state.goods.filter(item=>item.price >300)
}
}
})

通过属性进行访问

javascript
computed: {
totalPrice(){
return this.$store.getter.handle
}
}

传递参数

javascript
getters: {
powerCount(state){
return age => {
return state.students.filter(s => s.age > age)
}
}
},
html
<h2>{{ $store.getters.powerCount(20) }}</h2>

返回一个函数即可以传递参数

Mutation

前面的都不能对数据进行修改,mutation是专门对数据进行修改,且使用提交来进行修改,mutation都是同步事务

Javascript
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
//接受state作为第一个参数,es6写法注意下。increment:function(state){}
//或者increment:state=>state.count++
increment (state,params) {
// 变更状态
state.count++
//或者
state.count += params.mount
}
}
})

你当然不能直接调用(this.$store.mutation.increment)当然是不可能的!必须使用commit来进行触发

javascript
// 第一个参数为属性名,第二个是参数(载荷),可以是对象,或者其他基本类型。大多数为一个对象
store.commit('increment',params)
//如:
store.commit('increment',{
mount: 10
})

当然还有另一种的提交方式:对象风格的提交方式

javascript
store.commit({
type: 'increment', //事件类型
amount: 10 //参数,后续可以继续追加,获取得参数为一个对象
})

当使用对象风格的提交方式,整个对象都作为载荷传个mutation函数,因此increment不用变

vuex中的响应式原理,例如你给一个对象增加一个属性,页面是不会发生修改的,这时需要使用vue.set方法,同理删除一个属性页面也不会发生修改,使用vue.delete即可

Action

  • action 提交的是mutation,不是直接变更状态(state)
  • action可以执行任何异步的操作
  • 参数为context,上下文。而不是和其他一样state
javascript
actions: {
increment ({ commit }) //这里使用的是解构赋值,action的一个参数为context(可以理解为store,store中有commit操作,也可以解构多个参数{state,commit,rootState})
commit('increment')
}
}

Action 通过 store.dispatch 方法触发:

Javascript
store.dispatch('increment')

因此异步操作都可以放入action中,通过action再触发mutation

state

Javascript
info: {
name: 'kebe',
}

mutations

Javascript
updateInfo(state){
state.info.name = 'codewhy'
}

actions

Javascript
aUpdateInfo(context){
setTimeout(() => {
context.commit('updateInfo')
},1000)
}

组件中

Code
<button @click="upd">update</button>
upd(){
this.$store.dispatch('aUpdateInfo')
}

Module

vuex将store分割成多个模块,每个模块拥有自己的state、mutation、action、getter,同样也可嵌套子模块,----以同样的方式进行分割

javascript
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 的状态

命名空间

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

如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名.

Author: Yo
Link: https://powerlrl.gitee.io/2020/02/27/前端/笔记/vuex/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 谢谢你请我吃糖果
    谢谢你请我吃糖果

Comment