vuex-辅助函数

vuex

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

vuex 安装

npm i vuex 

1 vuex核心概念

vuex是存储组件数据的集中式的仓库(如何优雅的读写仓库中的数据)

  • state:仓库内存数据的配置

  • getters:仓库内的计算属性

  • action:操作数据的工具

  • mutation:操作数据的工具

仓库

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

  1. Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,
    若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  2. 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地
    提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,
    从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

2 state-基本环境配置

创建文件store,文件store.js 引入并暴露

2.1 将vuex注册为vue的插件

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

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)
注意

上述步骤必须在创建仓库之前完成!

2.2 新建仓库

Vuex 通过new Vuex.Store({配置对象})来新建一个仓库
仓库的所有数据保存在配置对象的state属性中

// 如果在模块化构建系统中,请确保在开头调用了 Vue.use(Vuex)
// 在src目录下新建store目录   再新建index.js文件来存放仓库
import Vuex from "vuex" 
const store = new Vuex.Store({
  state: {
    count: 0
  }
})
export default store

2.3 注册仓库

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

import store from './store'
new Vue({
  store,    //import一个文件,该文件内的代码会被执行,暴露出来的内容也会被拿到
})

2.4 访问仓库数据

由于上一步把 store 的实例注入了所有的子组件 所以任何组件都可以通过其自身的$store来访问仓库 在component新建count.vue

<template>
  <div>
    {{count}} // 没有响应式
    //{{$store.state.count}}  有响应式 若被input直接使用,会出现脏数据
  </div>
</template>
<script type="text/ecmascript-6">
    export default {
        name: "App",
        data(){
          return {
            count:this.$store.state.count
          }
        }
    }
</script>

注意:

  • 仓库内部的state和getters都会转绑给仓库对象
  • Vue.prototype. s t o r e : 代 表 的 就 是 仓 库 对 象 , 任 意 一 个 组 件 都 可 以 通 过 store:代表的就是仓库对象,任意一个组件都可以通过 storesrore这个属性;来访问到这个仓库{{$store.state.count}}
  • 仓库中的数据也是响应式的
  • 仓库中的数据也不能直接在组件上读取,任意产生脏数据,应该使用计算属性读取仓库中的数据
	computed:{
          count:{
            get() {
              return this.$store.state.count
            },
            set(newCount) {
              console.log(newCount)
            }
          }
        }

在整个组价的改造过程中,我们发现是需要修改计数器的值,
当我们通过 this.$store.state.count++ 这种方式去修改store中的数据时发现仓库数据变了
可是界面上的数据没有更新. 在对仓库数据进行修改时 我们必须遵守 Vue 的响应规则

2.5 严格模式

开启严格模式,仅需在创建 store 的时候传入 strict: true

const store = new Vuex.Store({
// ...
strict: true
})

在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。
这能保证所有的状态变更都能被调试工具跟踪到。

3 Mutation-修改数据

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

3.1 注册Mutation

	const store = new Vuex.Store({
      strict: true,
      state:{
        count:0
      }, //修改仓库数据的工具
      mutations:{
        add(state){
          state.count++
        },
      }
    })
    export default store

3.2 使用mutation

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

store.commit('add')

3.3 提交载荷(Payload)

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

mutations: {
  add (state, step) {
    state.count += step
  }
}
methods:{
    add() { this.$store.commit("add",2)}
}

在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读:

mutations:{
    add(state,{step,msg}) {
      state.count += step
    }
  }
add() {this.$store.commit("add",{step:2,msg:"hello"})}

3.4 对象风格的提交方式

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

		add() {
            this.$store.commit({
              type:"add",
              step:2,
              msg:"hello"
            })
          }

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

mutations:{
    add(state,{step,msg}) {
      state.count += step
    }

3.5 Mutation 需遵守 Vue 的响应规则

既然 Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:

  1. 最好提前在你的 store 中初始化好所有所需属性。

  2. 当需要在对象上添加新属性时,你应该

  • 使用 Vue.set(obj, 'newProp', 123)

注意:

Mutation 必须是同步函数

vue 的 devtool 中会记录每一条 mutation 日志。如果mutation中存在异步代码,会导致devtools中的记录变的混乱不可维护, 当我们在mutation中书写异步代码时,严格模式下vue会提出警告,非严格模式下vue不会做出任何反应

4 Action-操作数据

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

4.1 使用

让我们来注册一个简单的 action:

//进行同步注册
mutations:{
    asyncAdd(state,step) {
      state.count += step
    }
  },
//再异步修改仓库数据
  actions:{
    asyncAdd(store,step){
      //store: 仓库对象
      setTimeout(()=>{
        store.commit("asyncAdd",step)
      },2000)
    }
  },

4.2 分发 Action

Action 通过 store.dispatch 方法触发使用:

<button @click.stop="asyncAdd">aysnc btn(2000)</button> //会有冒泡,因此用stop阻止 
methods:{
    asyncAdd(){
      // this.$store.commit("asyncAdd",3)
      this.$store.dispatch("asyncAdd",3)
    }
}

Actions 支持同样的载荷方式和对象方式进行分发:

  • 以载荷形式分发:store.dispatch(‘asyncAdd’,{step:3}
  • 以对象形式分发
  • map辅助

5 Getter-计算属性

有时候我们需要从 store 中的 state 中派生出一些状态.如果有多个组件需要用到此状态
就可以在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,
getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

Getter 接受 state 作为其第一个参数:
// 仓库文件
getters: {
    flag(state) {
      return state.count%2===0 ? "偶":"奇"
    }
  },

访问Getter

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

computed: {
    flag(){
      return this.$store.getters.flag
    }
}

在这里插入图片描述

6 辅助函数

import { mapState,mapGetters,mapMutations } from 'vuex'

简化业务组件的开发

  • mapState({}) 或者 mapState([])
  • mapGetters({}) 或者 mapGetters([])
  • mapMutations({}) 或者 mapMutations([])
  • mapActions({}) 或者 mapActions([])

6.1 一般规律

  • vuex中的state 我们在组件中使用时通常需要有对应的computed
  • vuex中的getters 我们在组件中使用时通常需要有对应的computed
  • vuex中的mutations 我们在组件中使用时通常需要有对应的methods
  • vuex中的actions 我们在组件中使用时通常需要有对应的methods

6.2 mapState用法

mapState(["count" ])    ==> 返回 {count(){return this.$store.state.count}}  
mapState({                            
  myCount:"count"      ==>   返回 {myCount(){return this.$store.state.count}}  
})
...mapState(["count"])

6.3 mapGetters用法

mapGetters(["flag"])    ==>   return this.$store.getters.flag
...mapGetters([flag])    //...表示把里面里面的数据展开显示

6.4 mapActions用法

...mapActions(["add","asyncAdd"])
传参可以在点击事件之后进行
 	<div class="count" @click="add(2)">
      {{count}}
      <button @click.stop="asyncAdd(3)">异步的函数</button>
    </div>

7 仓库中的数据读取到界面上(拿计算属性对应)

1. 仓库内部的state getters配置都会转绑给仓库对象
2. Vue.prototype.$store : 代表的就是仓库对象
    任意一个组件都可以通过 $store 这个属性来访问到仓库
3. 仓库中的数据也是响应式的    
4. 仓库中的数据也不能直接在组件上读取;任意产生脏数据
        我们应该使用计算属性来读取仓库中数据

8 如何优雅的修改仓库中的数据

同步修改: 
    组件上转发action
    action内部提交mutation 
    mutation内部同步的修改数据 
    界面得到更新
异步修改: 
     组件上转发action
     action内部处理异步逻辑;在异步完成时提交mutation 
     mutation内部同步的修改数据 
     界面得到更新

9 组件上写法的优化

mapState,mapGetters, 结合 ...运算符在vue的computed配置中结合使用
    computed:{
        ... mapState(["count"]) 
        ... mapGetters(["count"]) 
    }
mapActions,mapMutations 结合 ...运算符在vue的methods配置中结合使用
    methods:{
        ... mapMutations(["count"]) 
        ... mapActions(["count"]) 
    }
    传参: 在模板上使用方法时直接传参
mapState(["count"]) 
    {
        count:function(){
            return this.$store.state.count
        }
    }
mapState({myCount:count})
    {
        myCount:function(){
            return this.$store.state.count
        }
    }
mapActions(["add"])
    {
        add:function(payload){
            this.$store.dispatch("add",payload)
        }
    }
mapActions({myAdd:add}})
    {
        myAdd:function(payload){
            this.$store.dispatch("add",payload)
        }
    }    

10 vuex模块

mapState([ ]),mapState([{}) :当前这种使用形式,默认读取总仓库中的数据

如何将仓库分模块使用

① 定义分仓库:

export default new Vuex.Store({
	//vuex模块
  modules:{
    a
  }
}
	export default {
          state:{test:"a模块中的test"},
          getters:{},
          mutations:{},
          actions:{}
        }

注册分仓库

② 如何读取总仓库的数据

mapState({key:()=>{}});   mapState中的参数是一个对象 {key:函数}
函数的返回值才是真正要被渲染的数据!
当前函数的参数是总仓库中的state
...mapState(["test"]),

③ 如何修改分仓库的数据

分仓库中的所有state数据是注册在当前模块下的;得通过 总仓库中的state.模块名.数据名 来访问
…mapState({组件上使用时的计算属性的名称:state=>state.模块名.数据名})

...mapState({testFromA:state=>state.a.test}),

④ 如何修改分仓库总仓库的数据

在总仓库中出现的所有 state都代表是总仓库自己的state
在分仓库中出现的所有 state都代表是分仓库自己的state
不管是总仓库中mutation,actions;getters 还是分仓库中的mutation,actions;getters 都是定义在全局的!
所以修改分仓库的数据 还是 按照总仓库的模式进行处理!

 state:{
    test:"总仓库中的test"
  },
  mutations:{
    updateTest(state){
      state.test = "总仓库中的 copy test"
    }
  },
  actions:{
    updateTest(store){
      store.commit("updateTest")
    }
  },
//在分仓库中出现的所有 state都代表是分仓库自己的state
export default {
  state:{
    test:"a模块中的test"
  },
  getters:{
    getDataFromA(state){
      return  state.test+"-getters"
    }
  },
  mutations:{
    updateATest(state){
      state.test = "a模块中的 copy test"
    }
  },
  actions:{
    updateATest(store){
      store.commit("updateATest")
    }
  }
}

注意:

  • mapState([“state中数据的名称”]);mapState({key:“state中数据的名称”});
  • mapState中的参数是一个数组 或者 对象 {key:string}的时候
  • 默认读取的都是总仓库中的数据;

什么 样的数据应该进仓库?

多组件共享的数据都要放仓库,请求相关的数据也要放仓库

11 小练习

store.js npm i vuex 配置 暴露 拆分组件 新建文件并往外暴露对象

main.js注册vuex配置

state.js 把所有(list search)data中的数据放入到这里 辅助函数

search.js username需要修改,辅助做不到,因此自己写(get set)在actios mutations中进行编写

flag的修改同username actions修改稿数据后记得触发(methods)

list.vue 总线不要了 发送请求在actions中,数据都在仓库中

在search中发送请求,点击search才有的数据

【】拿到的是变量,不是字符串

 store.commit("updateATest")
}

}
}




**注意:**

- mapState(["state中数据的名称"]);mapState({key:"state中数据的名称"}); 
- mapState中的参数是一个数组 或者 对象 {key:string}的时候
-  默认读取的都是总仓库中的数据;



什么 样的数据应该进仓库?

多组件共享的数据都要放仓库,请求相关的数据也要放仓库

# 11 小练习

store.js  npm  i vuex 配置 暴露 拆分组件 新建文件并往外暴露对象

main.js注册vuex配置   

state.js 把所有(list search)data中的数据放入到这里  辅助函数

search.js  username需要修改,辅助做不到,因此自己写(get set)在actios  mutations中进行编写 

flag的修改同username  actions修改稿数据后记得触发(methods)

list.vue   总线不要了 发送请求在actions中,数据都在仓库中

在search中发送请求,点击search才有的数据

【】拿到的是变量,不是字符串



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值