Vuex 入门

Vuex用法

前言:

vuex, 是vue 的一个插件,作用是 对vue应用中多个组件的共享状态进行集中式的管理(get/set)

用着用着 感觉回到了学Java的时候,写的 entity class,里面一堆的 getter setter

为解决多组件共享状态问题而生:

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

以前的解决方法:

  • 将数据以及操作数据的行为 全部集中定义在父组件中
  • 将数据以及操作数据的行为传递给需要的子组件,(可能要逐层传递)

  1. 根据vue cli 3.0 搞法 在src 目录下新建 store文件夹

  2. store文件夹下面 新建 index.js 文件

  3. 导入前置

    import Vue from 'vue'
    
  4. 导入 vuex

    import Vuex from 'vuex'
    
  5. 声明使用 vuex

    Vue.user(Vuex)
    
  6. 实例化对象

    const store = new Vuex.Store()
    
  7. 模块化编程的时候记得向外暴露对象

    export default store
    
  8. main.js 中引入

    import store from './store/index.js'
    
  9. 在vue 实例中使用

    new Vue({
      store, //这里
      render: h => h(App),
      /*
      *  h 是方法, 是箭头匿名函数的 第一且唯一参数, 函数体返回 一个函数调用的结果
      *  h 的解释是 Hypescript 是一个生成 HTML结构 的script 脚本 ,
      *
      *  体现在 vue 1.0 中为
      *   components: {
      *     App
      *   }
      * */
    }).$mount('#app');
    

Vuex 中的各大模块

属性名作用
state用于数据的存储,是store中的唯一数据源
getters如vue中的计算属性一样,基于state数据的二次包装,常用于数据的筛选和多个数据的相关性计算
mutations类似函数,改变state数据的唯一途径,且不能用于处理异步事件
actions类似于mutation,用于提交mutation来改变状态,而不直接变更状态,可以包含任意异步操作
modules类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护
  1. 标准用法(简写)
export default new Vuex.Store({
  state: {
    // 任何地方都能 this.$store.state.xxx 了
  },
  getters: {
    /* 不过get 提供了更好的获取方法,由于直接获取不能做一些 state 的操作,
      而在 getters 中你可以写自己想要的 getter 逻辑
      命名规则一般以 get 开头
     */
  },
  mutations:{
    /*
    	一般是写 set 函数,改变state数据的唯一途径,不能写异步
    	命名规则一般以 set 开头
    */
  },
  actions:{
  	/*
  		用来提交 mutations ,在其中可以写与后台交互的 ajax 异步代码,
  	*/                            
  }
   modules:{
       // 项目大的时候需要很多个状态,那么拆开作为各个模块来使用 状态管理
   }
})

Vuex 结构图的理解

在这里插入图片描述

流程的解释:

  1. 初始化开始(初始化阶段)

  2. vue components 向 vuex 中的 state 建立依赖( get )

    还记得嘛?computed属性在 组件实例的初始化阶段就会默认的get 一次

    所以这个过程也是自动 get 一下vuex 中的依赖

  3. 更新开始(更新阶段)

  4. 在组件中的依赖的数据要发生改变时,通过dispatch ()分发

  5. dispatch() 找到对应 actions中的方法名

  6. actions 通过 commit()去往对应的 mutations

  7. mutations直接更新 state 中的数据(set)

了解完了几大组成,现在来说说 backenddevlools

backend:

适用于在actions 中写 ajax 代码与后端通信

devlools:

在 chrome 的 开发工具中,提供了监视 mutations 的一个视图,开发人员可以查看

Vuex 使用示例

export default new Vuex.Store({
  state: {
    count:1,
    allStatus:false
  },
  getters: {
    getCount(state){ //命名规范
      return state.count;	// 注意这里不能用this 此时的 this是 undefined,估计是使用了严格模式
    },
    getAllStatus(state){
      return state.allStatus	// 错误示例 :return this.state.allStatus 
    }
  },
  mutations:{
    setCount(state,num){
      state.count = num // 写其它操作
    }
  },
	...	// 此处展示最简单的用法
})
  • 其它组件实例中可以这样获取
this.$store.state.count // 属于直接获取,无监听 this 代表当前所在的组件

this.$store.getters.getCount // 不用加() ,因为它默认是计算属性,计算属性对应的默认方法就是get

在使用了 vuex 的状态管理后,组件实例上就多了一个 $store,方便组件的实例去获取依赖

  • 其它地方可以这样设置
this.$store.commit('setCount',1) // 第一个参数为所去方法,第二个为 携带参数

actions 提交 mutations

// mutations 中定义的一系列方法
mutations: {
	... 
    ,
    openAllstatus(state){
      state.allStatus = true
    },
    closeAllstatus(state){
      state.Allstatus = false
    }
}
// actions 中对应的写上 提交mutations
actions: {
    todoOpen(context){
      context.commit('openAllstatus')
    },
    todoClose(context){
      context.commit('closeAllstatus')
    }
  }
// 你还可能见到的写法为:
actions: {
    todoOpen({commit}){
      commit('openAllstatus')
    },
    todoClose({commit}){
      commit('closeAllstatus')
    }
  }
/* 在进入函数后,参数接收到值,用{} ES6语法来将 context 解构,拿到其中的commit 对象*/

最显而易见的方式就是在 组件中定义 一个 计算属性 get 一下 对应的 state 中的值 来查看 提交的更新

computed: {
  allStatus(){
      return this.$store.getters.getAllstatus  
      // chrome vue development 中选择对应的组件可以看到,确确实实更新了
    }
}

现在试着在任意组件中合法的位置 通过action 提交 mutation

mounted: {
  this.$store.dispatch('todoOpen');  // 调试查看 计算属性中的值,已经发生改变 为 true
}

使用vuex中的 map映射将代码优雅化

import {mapState,mapGetters,mapActions} from 'vuex' //解构赋值,名字不能瞎取

我们之前是这样写的:

this.$store.state.count // 属于直接获取,无监听 this 代表当前所在的组件

this.$store.getters.getCount // 不用加() ,因为它默认是计算属性,计算属性对应的默认方法就是get

改变下写法用新的API,两条代码分别相等,对应

...mapState(['count'])		//相当于是state的语法糖,记得放在 computed里面,标识它是一个计算属性
...mapGetters(['getCount'])	//相当于是getters的语法糖,记得放在 computed里面,标识它是一个计算属性

/*
	三个点是 ES6 的拓展运算符,了解一下,在此处用作`对象展开`
	我不反对你把 mapState,mapGetters放在 data 中(普通属性)
	但它应该有自己的样子,请将mapState,mapGetters 移到  computed中(计算属性)
	在 vuex 状态管理中找到对应的组件,可以看到值出现在 vuex bingdings里面
*/

mapState的返回值:

{
    count(){
        return this.$store.state['count'] //去 store 中的 state数据源找到 count 属性
    }
}

mapGetters的返回值:

{
    getCount(){
        return this.$store.getters['getCount'] // 去getters 中的 getCount 方法
    }
}

比如需要获取 count,或者是其他值的时候

...mapState(['count','value1','value2'])

对象展开生成后:

{
    count(){
        return this.$store.state['count'] //去 store 中的 state数据源找到 count 属性
    },
    value1(){
        return this.$store.state['value1']
    },
    value2(){
        return this.$store.state['value2']
    }       
}

之前用来 分发提交 actions 的动作就变成:

this.$store.dispatch('todoSetxxx')

/*  变成下面这样  */
/*  v v v v v  */
...mapActions(['todoSetxxx'])		// 放在 methods 里面

组件的实例中操作 actions

this.todoSetxxx()
this.todoSetxxx(data) //可携带参数,请与actions中相对应

dispatch 提交多参数时参数接收的解决

有时候需要传递多个参数给 actions ,然后再 提交mutations 来改变state中的状态
像下面这样:

this.$store.dispatch('actionName',params1,params2)

//或者是 使用了  ...mapActions
...mapActions(['actionName']) //定义在了 methods 里
this.actionName(params1,params2) //与第一行相等

actions中输出时你会发现,params2 的值为 undefined
也就是说它的默认接参只支持两个,第一个为 dispatch的提交,第二个为用户指定参数, 注 意 : \color{#ff0000}{注意:} mutations 中的方法也只接受两个参数

解决方法如下:(使用解构赋值)

传多个参数时:

this.$store.dispatch('actionName',{params1,params2})

actions中解构出来

actionName({commit},{params1,params2}){
	commit('mutationName',{params1,params2}) //传递的时候也要包装起来
}

对应的 mutations中的方法,接受参数时也得 解构出来

mutationName(state,{params1,params2}){
	
}

需要注意的是使用解构赋值的时候,从头至尾的参数名称要一 一对应,不然解构不出来

Modules 将状态模块划分

一旦项目大起来,一个store > index.js 中可能塞满了各种各样的 state,维护将变得困难,modules 提供了管理办法 。

1. 建立如下方式的目录:

在这里插入图片描述

此时 index.js作为一个入口,在入口中引入拆分的状态,index.js中只留modules ,mutation-types 是常量字符串映射值,可有可无。

2. 配置单个状态如下:

const state = {
 	// 定义状态
}
const getters = {
	// get State
}
const mutations = {
 	// set State
}

const actions = {
	// 提交 mutations
}

export default { //向外导出
  namespaced: true, // 开启命名空间,将modules 里面配置的对象指定一个名字方便管理
  state,
  getters,
  actions,
  mutations
}

3. 在组件内部使用状态

这个时候因为状态被拆分了,且具有自己的名称,组件在创建后,vue 给组件加入了 $store,也可使用引入mapState,mapGetters,mapMutations,mapActions来使用,但是得加上模块名称

假设我在 userInfo 状态模块里面管理了一个状态

const state = {
 	user:{
        username:""
    }
}
const getters = {
	getUserName(state){
        return state.user.username
    }
}
const mutations = {
    setUserName(state,val){
        state.user.username = val
    }
}
const actions = {
    changeUserName(context,val){
        context.commit('setUserName',val)
    }
}

使用:state , mapState
this.$store.state['userInfo'].user.username
...mapState('userInfo',['user'])

this.user.username
使用:getters , mapGetters
this.$stroe.getters['userInfo'].getUserName
...mapGetters('userInfo',['getUserName'])

this.getUserName
使用:commit
this.$store.commit('userInfo/setUserName')
使用:dispatch,mapActions
this.$store.dispatch('userInfo/changeUserName')

...mapActions('userInfo',['changeUserName'])

4. 在组件外部使用

vue 不提供 $store的注入,所以先引入 store

import store from '../store'  // 默认下面如果是 index.js,那么可以省略不写

且无法使用 mapXXX,那么使用原始的操作也一样

store.dispatch('userInfo/changeUserName') // 举一个例子,其它的语法照着写就是
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值