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'
    
  1. 声明使用 vuex

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

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

    export default store
    
  4. main.js 中引入

    import store from './store/index.js'
    
  1. 在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. 建立如下方式的目录:

image-20200208202544722.png

此时 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') // 举一个例子,其它的语法照着写就是
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容

  • 本文目录: 1.Vuex的定义 2.Vuex的使用流程 3.Vuex的核心概念 4.辅助函数mapState、ma...
    前端辉羽阅读 323评论 0 7
  • Vuex是什么? Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件...
    萧玄辞阅读 3,070评论 0 6
  • 安装 npm npm install vuex --save 在一个模块化的打包系统中,您必须显式地通过Vue.u...
    萧玄辞阅读 2,901评论 0 7
  • 目录 - 1.什么是vuex? - 2.为什么要使用Vuex? - 3.vuex的核心概念?||如何在组件中去使用...
    我跟你蒋阅读 4,093评论 4 51
  • Vuex 是什么? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有...
    skycolor阅读 784评论 0 1