简单快速理解Vuex 图解 快速上手

1 篇文章 0 订阅

目录

Vuex 是什么?

五个核心的理解:

1、state: 存放需要管理的状态

2、getters:由基本数据派生/计算得出的数据(相当于State的计算属性)

3、Mutations:修改state的唯一方法(同步!)

Mutations 需遵守 Vue 的响应规则

4、actions:   异步通过提交mutation更改state

5、modules: 模块化Vuex

同步&异步的理解

         为什么要用Action管理异步操作


在不同组件,层级比较复杂,需要不同组件的某些状态保持同步,但是又不是单纯的父子关系。需要响应各个地方的更新变化,并保持一致,就需要用到Vuex,典型的像各个组件同步购物车数据/消息列表

1. vue中各个组件之间传值

   1.父子组件

   父组件-->子组件,通过子组件的自定义属性:props

   子组件-->父组件,通过自定义事件:this.$emit('事件名',参数1,参数2,...);

 

   2.非父子组件或父子组件

   通过数据总数Bus,this.$root.$emit('事件名',参数1,参数2,...)

 

   3.非父子组件或父子组件

   更好的方式是在vue中使用vuex

   方法1: 用组件之间通讯。这样写很麻烦,并且写着写着,估计自己都不知道这是啥了,很容易写晕。

   方法2: 我们定义全局变量。模块a的数据赋值给全局变量x。然后模块b获取x。这样我们就很容易获取到数据

 

 

Vuex 是什么?

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

,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

快速理解:state存状态,只有mutation可以操作在state存取状态(同步方式),actions是异步方法(通常是在这里向后台发请求拿数据)来操作mutation存取数据,不同组件内要运用state的状态,只需this.$store.state.xxx,调用actions只需this.$store.dispatch('xxx',xx)

 

 

五个核心的理解:

1、state: 存放需要管理的状态

用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT )”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。

所有的状态存储在一个公用的state中,组件使用 this.$store.state即可调用

 

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'
  或者count:state=>state.count  //理解为传入state对象,修改state.count属性
])


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

 在computed 使用,既可以随时监听变化,写法变得简单,在组件内就可以简单地通过this.count来引用

 

...mapState让你可以既有需要mapState的对象又有别的外部的对象

 

2、getters:由基本数据派生/计算得出的数据(相当于State的计算属性

从state基本数据派生的数据 对state的数据进行加工以后再让组件调用

getters接收state作为其第一个参数,接受其他 getters 作为第二个参数,如不需要,第二个参数可以省略如下例子:

const store = new Vuex.Store({
    state: {
        count:0
    },
    getters: {
        // 单个参数
        countDouble: function(state){
            return state.count * 2
        },
        // 两个参数
        countDoubleAndDouble: function(state, getters) {
            return getters.countDouble * 2
        }
    }
})


与state一样,我们也可以通过Vue的Computed获得Vuex的getters。

const app = new Vue({
    //..
    store,
    computed: {
        count: function(){
            return this.$store.state.count
        },
        countDouble: function(){
            return this.$store.getters.countDouble
        },
        countDoubleAndDouble: function(){
            return this.$store.getters.countDoubleAndDouble
        }
    },
    //..
}

 

基础用法:

main.js:

const store = new Vuex.Store({
  state: {
    list: [1, 3, 5, 7, 9, 20, 30]
  },
  getters: {
    filteredList: state => {
      return state.list.filter(item => item > 5)
    }
  }
})

index.vue:

<script>
  export default {
    name: "index.vue",
    computed: {
      list() {
        return this.$store.getters.filteredList;
      }
    }
  }
</script>

 

内部依赖

getter 可以依赖其它已经定义好的 getter。比如我们需要统计过滤后的列表数量,就可以依赖之前定义好的过滤函数。
main.js:

const store = new Vuex.Store({
  state: {
    list: [1, 3, 5, 7, 9, 20, 30]
  },
  getters: {
    filteredList: state => {
      return state.list.filter(item => item > 5)
    },
    listCount: (state, getters) => {
      return getters.filteredList.length;
    }
  }
})

index.vue:

<template>
 
  <div>
    过滤后的列表:{{list}}
    <br>
    列表长度:{{listCount}}
  </div>
</template>
 
<script>
  export default {
    name: "index.vue",
    computed: {
      list() {
        return this.$store.getters.filteredList;
      },
      listCount() {
        return this.$store.getters.listCount;
      }
    }
  }
</script>

 

3、Mutations:修改state的唯一方法(同步!)

提交mutation是更改Vuex中的store中的状态的唯一方法。

mutation必须是同步的,如果要异步需要使用action。

使用vuex修改state时,有两种方式:

1)可以直接使用 this.$store.state.变量 = xxx;

2)this.$store.dispatch(actionType, payload) (使用actions)或者 this.$store.commit(commitType, payload)

 

mutaitions  处理同步事件

每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。(提交荷载在大多数情况下应该是一个对象),提交荷载也可以省略的。

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    //无提交荷载
    increment(state) {
        state.count++
    }
    //提交荷载
    incrementN(state, obj) {
      state.count += obj.n
    }
  }
})

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

//无提交荷载
store.commit('increment')
//提交荷载
store.commit('incrementN', {
    n: 100
    })

 

对象风格的提交方式

我们也可以使用这样包含 type 属性的对象的提交方式。

store.commit({
  type: 'incrementN',
  n: 10
})

Mutations 需遵守 Vue 的响应规则

  • 最好提前在你的 store 中初始化好所有所需属性。
    • 当需要在对象上添加新属性时,你应该 
      • 使用 Vue.set(obj, 'newProp', 123), 或者
      • 以新对象替换老对象。例如,利用对象展开运算符我们可以这样写state.obj = {...state.obj, newProp: 123 }

 

与其他辅助函数类似,你可以在组件中使用 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({
      add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
    })
  }
}

 

4、actions:   异步通过提交mutation更改state

处理异步请求,在异步请求的回调函数当中去触发mutaitions中的函数,来同步的改变mutaitions中的值,像一个装饰器,包裹mutations,使之可以异步

Action 类似于 mutation,不同在于:

  • Action 通过提交 mutation 来间接修改状态, 而不是直接变更状态。
  • Action 可以包含任意异步操作。
  • 发请求一般就写再actions里

我们用如下例子来结束actions:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) { 
      setInterval(function(){
        context.commit('increment')//提交mutation来修改state
      }, 1000)
    }
  }
})

注意:Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象(一般可以写成{commit, state}就足够了),因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。

 

分发actions

在具体的组件中,Action 通过 store.dispatch 方法触发,使用:

store.dispatch('increment')

dispatch 异步操作 this.$store.dispatch('actions的方法',arg)

commit 同步操作 this.$store.commit('mutations的方法',arg)

 

 

5、modules: 模块化Vuex

背景:在Vue中State使用是单一状态树结构,应该的所有的状态都放在state里面,如果项目比较复杂,那state是一个很大的对象,store对象也将对变得非常大,难于管理。
module:每个模块拥有自己的 state、mutation、action、getters、甚至是嵌套子模块使得结构非常清晰,方便管理

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管理异步操作

需求如下

state中存储了一个状态count

现在有两个异步操作,他们都能改变count的值

第二个异步操作的条件依赖第一个异步操作的结果,比如第一个异步操作执行了count ++ ,count :0 = >1,第二个异步操作会先判断当前count的值,if(count === 1) { do something...} else { do something... }

 当异步操作涉及互相依赖的情况的时候,我们肯定希望被依赖的操作执行完成之后,再执行依赖项,这样能保证程序执行得到正确的结果,但异步操作,如接口访问这种,往往是不能确定执行完成的时间的,

通常你在接口A中得到一个值,a

接口B需要使用这个值结合B接口返回的值进行一些判断操作,if(a&&b){ ... }

这个时候如果B接口执行完毕了,A接口的值还没过来的话,就可能得到错误的结果。 a => undefined

  所以这里牵扯到了一个异步操作的顺序执行问题,既然是异步操作问题,基本都会用到ES6的promise函数去解决,有兴趣的可以用看一下文章——关于promise的一些使用和原理。

ES6语法(3)—— 用promise()对象优雅的解决异步操作

 

结合async/await的异步函数
 

asyn function(){
    let f = await f1()
    ....
}

是一个会等待f1执行完再继续的异步,保证了有依赖关系的时候数据的正确性。

若是两个函数之间有依赖关系,比如必须要等f1执行完了再执行f2

有些要等请求发完了再执行的操作就可以使用


    DoSomething({commit, state}, n) {
        return new Promise(async (resolve, reject) => {
            let n = .....
            let res = await DoSomething(n)
            if (res.operateCode === 'S') { 
                commit(DO_OTHER_THING, n)
                dispatch('OTHER_THING')
                //.....
            } else {
                console.log('error')
            }
        })

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值