Vuex的五大概念和方法

152 阅读3分钟

vueX

vuex介绍

为什么有vuex?

在现代 Web 开发复杂多变的需求驱动之下,组件化开发已然成为了事实上的标准。

然而大多数场景下的组件都并不是独立存在的,而是相互协作共同构成了一个复杂的业务功能。

vuex是什么?

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

vuex的使用

下载vuex插件(可看官网选择用3还是4)

npm insrtall vuex@3

在src/story目录下的文件index.js引用vuex组件

//引入vue组件,来进行使用
import Vue from "vue";
// 引入vuex
import Vuex from "vuex";

//实例化Vuex对象里面的Store,要记得大写
const store = new Vuex.Store({
    //键值对的形式:state(存放变量),mutations(同步的方法),actions(异步的方法),getters(跟计算器一样的性质),modules(模块)
})
//state,mutations,actions多数写在不同的modules内,getters一般是全局(组件)

// 通过Vue去使用Vuex
Vue.use(Vuex)

// 把实例化的store导出去
export default store

在main.js文件下引用vuex组件

import Vue from 'vue'
import App from './App.vue'
//引用声明为store,暴露出来的实例vuex.store组件
import store from '@/story/index'


Vue.config.productionTip = false

new Vue({
 //在Vue实例里面去注册该store组件
  store,
  render: h => h(App),
}).$mount('#app')

概念一 state

介绍

官方:

  1. state是放置所有公共状态的属性,每一个公共状态数据 , 都可以定义在 state对象中来全局调用
  2. 一般都是写在各自模块里面的

**白话:**state是vuex提供给我们声明全局变量的对象,如果我们想要声明一个全局变量,那么只需要把这个变量声明在state对象中即可

定义

const store = new Vuex.Store({
   state:{
       //管理数据
       //例如存进健名count的变量健值为1
       count:1
   }
})

使用

如下面三种方法都可获得定义的count健值1通过插值表达式显示在div内

原始形式---插值表达式

//在组件中可以使用this.$store获取到vuex中的store对象实例,通过state.语法可以获得属性
<div>
state的数据:{{$store.state.count}}
</div>

计算属性 - 将state属性定义在计算属性中

//把state中数据,定义在组件内的计算属性中
computed:{
   count(){
           return this.$store.state.count
}
}

在template的文件里调用该属性

<div>
    state:{{count}}
</div>

辅助函数 - mapState

  • 引入mapState
import {mapState} form 'vuex'
  • 采用数组形式引入state属性,利用延展运算符将导出的状态映射给计算属性
computed:{
    ...mapState(['count'])
}

概念二 mutations

介绍

官方:state数据的修改只能通过mutations,并且mutaions必须是同步更新**,目的是形成**‘数据快照’**

白话:mutations是vuex专门提供给开发来修改state数据的对象,mutations中只能写同步代码。

定义

mutations是一个对象,在里面存储修改state的方法

const store = new Vuex.Store({
   state:{
       //管理数据
       //例如存进健名count的变量健值为1
       count:1
   }
    mutations:{
    //方法里参数 第一个参数是当前store的state属性
    
    //payload 载荷 运输参数 调用mutaions的时候 可以传递参数 传递载荷(根据情况看是否需要进行传参)
    addCount(state,payload){
    //方法的意思是state的count属性加上payload传递过来的实参
    state.count +=payload
}
}
})

使用

如下面两种方法都可实现通过mutations里的方法去修改state的值

**调用方法 -$store.commit.方法名 **

  1. 将mutations属性定义在方法的函数内
  2. 直接在文档内容调用该方法
<template>
    <button @click='$store.commit.addCount(1)'>+1</button>
</template>

<script>
export default {
  methods: {
    
      // 调用store中的mutations提交给mutaions
      // commit('muations名称',需要传进去的参数)
      this.$store.commit('addCount', 1)// 直接调用mutations
    
  }
}
</script>

辅助函数 - mapMutations-

  1. 采用数组形式引入mutations
  2. 利用延展运算符将导出的状态映射给methods
<template>
    <button @click='addCount(1)'>+1</button>
</template>

<script>
   import { mapMutations } from 'vuex'
export default {
  methods: {
   ...mapMutations(['addCount'])
  }
}
</script>

概念三 actions

介绍

官方:state是存放数据的,mutations是同步更新数据,actions则负责进行异步操作

白话:actions负责异步操作(通常都是ajax请求),然后通过mutations来间接修改state中的数据。

定义

 actions: {
      // 获得异步的数据store表示当前store的实例
     //相当于const store=new Vuex.store()
     //可以通过store.state获得状态,也可以通过store.commit来提交mutations,也可以store.deapatch调用其他的action
      getAsyncCount(store){
        setTimeout(function () {
          // 一秒钟之后 要给一个数 去修改state
          store.commit('addCount',1)
          
        },1000)
      }
    }

使用

原始形式-$store.dispatch.方法名


<script>
export default {
  methods: {
      //通过方法封装异步函数
  addAsyncCount(){
this.$store.dispatch('getAsyncCount')
}
  }
}
</script>

辅助函数-mapActions

  1. 导入mapActions
  2. 采用数组形式导入actions
  3. 利用延展运算符将导出的状态映射给methods
<template>
    //4.直接调用该异步方法
    <button @click='getAsyncCount'>+1</button>
</template>

<script>
    //1.引入mapActions
import { mapActions } from 'vuex'  

export default {
  methods: {
      //2.采用数组形式导入actions
      //3.利用延展运算符将导出的状态映射给methods
...mapActions(['getAsyncCount'])
  }
}
</script>

概念四 getters

介绍

官方:除了state之外,有时我们还需要从state中派生出一些状态,这些状态是依赖state的,此时会用到getters(等于计算器compted)

白话:除了state之外,我们还有能够通过getters来声明全局变量,而这些声明getters中的变量的值是依赖于state中的数据得来。

定义

主要作用(使用场景):就是简化state中变化访问

//getters对象里面,可以声明任意的属性
//只要属性的值是一个函数,并且这个函数能够默认接收到state参数
//这个state参数就是指和getter统计的state

const store = new Vuex.Store({
   state:{
       //管理数据
       //例如存进健名count的变量健值为1
       count:[1,2,3,4,5,6]
       
   }
    getters:{
    getCountGiger3(state){
    //必须要有返回值
    return state.count.filter(res=>res>3)
}
}
})

使用

原始形式-$store.getters.属性名

<template>
    //展现大于3的数字
    <h1>
    {{$store.getters.getCountGiger3}}
    </h1>
</template>

辅助函数-mapGetters

<template>
    //4.直接调用该异步方法
    <h1 >{{getCountGiger3}}</h1>
</template>

<script>
    //1.引入mapGetters
import { mapGetters } from 'vuex'  

export default {
  compted: {
      //2.采用数组形式导入getters
      //3.利用延展运算符将导出的状态映射给compteds
...mapGetters(['getCountGiger3'])
  }
}
</script>

概念五 module

介绍

官方:由于使用单一状态树,应用的所有状态会集中到一个比较大的对象state中,当应用(项目)变得非常复杂的时候,就有可能变得相当臃肿。vuex会变得越来越难以维护,由此,有了vuex的模块化。(将一个大板块分成每个不同的区域)

白话:因为所有的数据都是声明在state对象中的,当我们的项目变得非常复杂的时候,我们的state对象就会变得相当臃肿,vuex就变得难以维护,由此,有了vuex的模块化,也就是分模块来保存数据

定义

官方:

1、vuex专门提供了一个modules属性给我们声明模块,这个属性只要写在和state、mutations、actions、getters同级的位置上即可。

2、直接在modules中声明模块即可,每个模块都有state、mutations、actions、getters、modules

白话:

  1. 除了分区和可以用密码锁变成局部,和全局一样有state,mutations,actions,getters,modules5大模块,
  2. 但默认模式下(不启用密码锁)除statemutations要通过模块名访问,其他mutations,actions,getters默认是注册在全局的
const store = new Vuex.Store({
    state:{},
    mutations: {},
    actions: {},
    getters: {},
    modules: {}
})

使用

const store = new Vuex.Store({
    modules: {
    //在模块内声明user和setting两个模块放置state的属性
        user: {
            state: {
                count:1
            }
        },
        
        setting: {
            state: {
                name: '李好'
            }
        }
    }
    //getters依赖sate的方式可以方便优化调用方式
    getters:{
    //声明一个属性去承载获取方式
    count:state=>state.user.count
    
    name:state=>state.setting.name
    
})

原始形式-$store.state.模块名.属性名(5大概念都可以使用,不止state)

<h1>
    //获取user模块中的count
    {{$store.state.user.count}}
</h1>

优化使用-利用getters依赖state的属性和mapGetters辅助函数

<template>
    //4.直接调用mapGetters数组里面的属性名显示
    <h1 >{{count}}</h1>
    <h1 >{{name}}</h1>
</template>

<script>
    //1.引入mapGetters
import { mapGetters } from 'vuex'  

export default {
  compted: {
      //2.采用数组形式导入getters
      //3.利用延展运算符将导出的状态映射给compteds
...mapGetters(['count','name'])
  }
    
</script>

修改模块的数据

默认情况下,模块内部的action、mutations、getters都注册在全局的。(如下图)

  • 定义在模块内的方法
const store = new Vuex.Store({
    modules: {
    //在模块内声明user和setting两个模块放置state的属性
        user: {
            state:{
                count:1
            },
           mutations:{
               addCount(state){}
               state.count++
           }
        },
      
})
  • 调用该模块内方法(默认情况下和全局一致)
<template>
    //调用这个模块的方法
    <button @click='$store.commit('addCount')'>点击自增1</button>
   
</template>

让模块中的mutations具有独立命名空间(局部域)

介绍

通过namespaced属性设置为true, 从而给user模块加一道锁,此刻user模块中的所有内容都是局部的,都必须通过模块名才能访问到,该模块叫独立的命名空间

定义

const store = new Vuex.Store({
    //模块
    modules: {
    //通过给namespaced的健值为true给下面的每个模块(例如user模块)添加一把锁,必须要通过模块名才可以访问的到
        namespaced:true;
        
//在模块内声明user模块和user模块下的mutations的方法
        user: {
            state:{
                count:1
            },
           mutations:{
               addCount(state){}
               state.count++
           }
        },
      
})

如何访问添加密码锁的模块方法('模块名/函数名')

<template>
    //调用这个模块的方法
    <button @click='$store.commit('user/addCount')'>点击自增1</button>
   
</template>