首页 > 其他分享 >Vuex

Vuex

时间:2024-07-02 16:32:08浏览次数:18  
标签:const value state store Vuex totalNum

Vuex

什么是Vuex?

概念:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对应用中多个组件的共享状态进行集中式管理(读/写),也是组件间通信的方式,且适用于任意组件间通信

之前想要传递数据,可以使用全局事件总线/消息订阅去实现,但是如果有很多组件都想要去读和写 某个组件中的数据,那么需要在每个组件中去绑定或触发 读/写的事件,一旦组件数过多代码就会变得很复杂,所以可以使用vuex去实现这个目的。

 

Vuex 工作原理

vuex

在Vuex中有三个对象 Actions、Mutations、State

State 里面保存的是 数据,以key-value 的形式保存

 

一个动作/函数 的执行流程:

  • 在Vue 组件中 点击了加1按钮,想让一个数字加1,但这个数字不在该组件自身,在Vuex的state里

  • 调用dispatch() 第一个参数是 要进行的动作类型,比如是”add“,第二个参数是 要加几

  • 调用了dispatch后,你执行的动作和值就来到了 Actions,Actions也是一个Object对象,里面一定会有一个“ add”,它的值是一个函数,当你传进来的 “add” 能和 Actions中的 "add" 对上,就会引起 这个函数的调用,这个函数一旦被调用就受到了传进来的 数值

  • 在 ”add“ 对应的函数中自己去调用 commit 函数 ,commit 函数 和 dispatch 函数的参数相同

  • 执行完 commit 函数后,就走到了 Mutations 对象中,它也有 ”add“ ,值也是 函数,在这个函数中 会拿到两个东西,第一个是 state 第二个是你传进来的数据,修改state 中的数据,底层会自动调用 Mutate,就会引起state 中数据的变化

  • 然后重新解析组件,渲染

在Action 中 发送 Ajax请求,当你不需要发送Ajax请求时,可以直接调用 commit 函数

上述三个对象 Actions、Mutations、State都是由Store管理的 ,调用也是通过store

 

搭建Vuex环境

1.安装Vuex

npm i vuex@3

这里我们需要安装vuex3版本,因为 vuex4只能在 vue3中使用

2.Vue.use(Vuex)

这里的注意点是 在 使用 Vue.use(Vuex) 必须在创建store 实例之前,所以需要先创建store实例

按照官网的写法,是在src目录下创建一个 store目录,在该目录下创建 index.js,在该文件中创建 store实例和使用 vuex插件

//该文件用于创建Vuex中最核心的Store
​
//引入Vue
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//使用vuex 插件
Vue.use(Vuex)
​
//准备Actions--用于响应组件中的动作
const actions = {}
//准备 mutations--用于操作数据
const mutations = {}
//准备state--用于存储数据
const state = {}
​
//创建并暴露 store
export default new Vuex.Store({
    actions,
    mutations,
    state
})

3.在 main.js 引入 store,并传入 vm 中

import Vue from "vue";
import App from './App'
import store from './store/index'
 
new Vue({
    el:"#app",
    render:h => h(App),
    store,
    beforeCreate(){
        Vue.prototype.$bus = this
    }
})

 

修改 计数案例

在没有使用vuex 的时候的计数案例:

<template>
  <div>
    <h1>当前的值为:{{totalNum}}</h1>
    <select v-model="selectNum">
        <option :value="1">1</option>
        <option :value="2">2</option>
        <option :value="3">3</option>
    </select>
    <button @click="addNum">+</button>
    <button @click="decrementNum">-</button>
    <button @click="addNumOdd">奇数加</button>
    <button @click="addWait">等会加</button>
  </div>
</template>
​
<script>
​
export default {
    name:'Counts',
    data(){
        return{
            totalNum:0,
            selectNum:1
        } 
    },
    methods:{
        addNum(){
            this.totalNum += this.selectNum
        },
        decrementNum(){
            this.totalNum -= this.selectNum
        },
        addNumOdd(){
            if(this.totalNum % 2){
                this.totalNum+=this.selectNum
            }
        },
        addWait(){
            setTimeout(() => {
                this.totalNum+=this.selectNum
            },500)
        }
    }
}
</script>
​
<style scoped>
    button{
        margin-left: 5px;
    }
</style>

 

使用 Vuex来修改计数案例

按照Vuex的执行流程

  • 首先把 定义在 Counts组件中的数据 放到 store 的 state 对象中

    const state = {
        totalNum:0
    }
  • 在 Counts 组件的方法中调用 dispatch

    methods:{
            addNum(){
                this.$store.dispatch("addNumber",this.selectNum)
            },
            decrementNum(){
                this.$store.dispatch("decrement",this.selectNum)
            },
            addNumOdd(){
                if(this.$store.state.totalNum % 2){
                    this.$store.dispatch("addNumber",this.selectNum)
                }
            },
            addWait(){
                setTimeout(() => {
                    this.$store.dispatch("addNumber",this.selectNum)
                },500)
            }
    }
  • 在 store的 actions 和 mutations 中 定义 dispatch 传入的方法

    const actions = {
        addNumber(context,value){
            context.commit("ADDNUMBER",value)
        },
        decrement(context,value){
            context.commit("DECREMENT",value)
        }
    }
    //准备 mutations--用于操作数据
    const mutations = {
        ADDNUMBER(state,value){
            state.totalNum += value
        },
        DECREMENT(state,value){
            state.totalNum -= value
        },
    }
  • 在之前的模板中 的差值语法不能直接使用 totalNum,而是 用 $store.state.totalNum

如果没有网络请求或其他业务逻辑,组件中 也可以越过actions,即不写dispatch,直接写commit

 

store 中的getters 配置项

1.当state中的数据需要经过加工后再使用,并且这个加工方式需要多次复用,可以在store 中配置 getters

2.getters 中计算出来的属性,用函数表示,参数是 state,还要把getters 传给Store

const getters = {
    bigSum(state){
        return state.sum * 10
    }
}
​
export default new Vuex.Store({
    ...
    getters
})

3.在组件中使用 $store.getters.bigSum 来获取这个值

 

四个map方法的使用

当我们在组件模板中去使用 state 中的数据时,每次都需要写 $store.state.xxx

我们就可以把 xxx 作为计算属性,“$store.state" 从计算属性中传过去,这样在模板中就简化了代码

但是 这样还会产生很多的计算属性,那么这时候就可以借助 vue提供的方法生成计算属性

  1. mapState:帮助我们映射state 中的数据为计算属性

    computed:{
        //第一种写法:对象写法
        ...mapState({sum:'sum',school:'school',subject:'subject'})
        //第二种写法:数组写法
        ...mapState(['sum','school','subject'])
    }

    需要注意 数组写法,必须保证计算属性的名字和 你想要在state中拿到数据的名字一致

    mapState 前的 "..." 的含义是 把 这个方法里面的对象追加到 computed中

  2. mapGetters:帮助我们映射getters 中的数据为计算属性

    使用方法和 mapState 相同,需要注意的是这两个方法需要从vuex 中用 import引入

  3. mapActions:用于帮助我们生成与actions对话的方法,即包含$store.dispatch(xxx) 的函数

    methods:{
        //第一种写法,对象写法
        ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
        //第二种写法:数组写法
        ...mapAction(['jiaOdd','jiaWait'])
    }
  4. mapMutation:用于帮助我们生成与 mutations对话的方法,即包含 $.store.commit(xxx) 函数

    使用方法和 mapActions 相同

注意:mapActions和 mapMutation 使用时,若需要传递参数,在模板中绑定事件时传递好参数,否则参数就是事件对象

下面是案例:

<template>
  <div>
    <!-- <h1>当前的值为:{{$store.state.totalNum}}</h1> -->
    <!-- <h3>当前的值放大十倍为:{{$store.getters.bigNum}}</h3> -->
    <h1>当前的值为:{{totalNum}}</h1>
    <h3>当前的值放大十倍为:{{bigNum}}</h3>
    <select v-model="selectNum">
        <option :value="1">1</option>
        <option :value="2">2</option>
        <option :value="3">3</option>
    </select>
    <!-- <button @click="addNum">+</button>
    <button @click="decrementNum">-</button> -->
    <!-- 调用方法时需要传参,否则参数就是鼠标点击事件-->
    <button @click="ADDNUMBER(selectNum)">+</button>
    <button @click="DECREMENT(selectNum)">-</button>
    <button @click="addNumOdd(selectNum)">奇数加</button>
    <button @click="addWait(selectNum)">等会加</button>
  </div>
</template>
​
<script>
import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'
export default {
    name:'Counts',
    data(){
        return{
            selectNum:1
        } 
    },
    computed:{
        ...mapState(['totalNum']),
        ...mapGetters(['bigNum'])
    },
    methods:{
        //这里用的都是 数组的方式,要求传入的名字要和store中 Actions和Mutations中的名字一致,使用时也是用这个名字
        ...mapActions(['addNumOdd','addWait']),
        ...mapMutations(['ADDNUMBER','DECREMENT'])
    }
}
</script>
​
<style scoped>
    button{
        margin-left: 5px;
    }
</style>
//准备Actions--用于响应组件中的动作
const actions = {
    addNumOdd(context,value){
        if(context.state.totalNum % 2){
            context.commit("ADDNUMBER",value)
        }
    },
    addWait(context,value){
        setTimeout(() => {
            context.commit("ADDNUMBER",value)
        },500)
    }
}
//准备 mutations--用于操作数据
const mutations = {
    ADDNUMBER(state,value){
        state.totalNum += value
    },
    DECREMENT(state,value){
        state.totalNum -= value
    },
}
//准备state--用于存储数据
const state = {
    totalNum:0
}
​
//准备getters--用于计算state中的数据
const getters = {
    bigNum(){
        return state.totalNum * 10
    }
}

 

Vuex模块化

目的:让代码更好维护,让多种数据分类更加明确

上面的案例只有一个组件,现在我们再创建一个组件,体现出多组件共享数据

<template>
  <div>
    <h1>人员列表</h1>
    <h3>列表中第一个人是:{{firstPerson.name}}</h3>
    <h3 style="color-red">Counts组件计算后的值:{{counts}}</h3>
    <input type="text" v-model="personName"> 
    <button @click="addPerson">添加</button>
    <button @click="addPersonWang">添加姓王的人</button>
    <ul>
        <li v-for="person in personList" :key="person.id">{{person.name}}</li>
    </ul>
  </div>
</template>
​
<script>
import {nanoid} from 'nanoid'
export default {
    name:'Persons',
    data(){
        return{
            personName:''
        }
    },
    computed:{
        personList(){
            return this.$store.state.personList
        },
        firstPerson(){
            return this.$store.getters.firstPerson
        },
        counts(){
            return this.$store.state.totalNum
        }
    },
    methods:{
        addPerson(){
            const person = {id:nanoid(),name:this.personName}
            this.$store.commit('ADD_PERSON',person)
            this.personName = ''
        },
        addPersonWang(){
            const person = {id:nanoid(),name:this.personName}
            this.$store.dispatch('addPersonWang',person)
            this.personName = ''
        }
    }
}
</script>
​
<style scoped>
    button{
        margin-left: 5px;
    }
</style>
//该文件用于创建Vuex中最核心的Store
​
//引入Vue
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//使用vuex 插件
Vue.use(Vuex)
​
//准备Actions--用于响应组件中的动作
const actions = {
    // addNumber(context,value){
    //     context.commit("ADDNUMBER",value)
    // },
    // decrement(context,value){
    //     context.commit("DECREMENT",value)
    // }
    addNumOdd(context,value){
        if(context.state.totalNum % 2){
            context.commit("ADDNUMBER",value)
        }
    },
    addWait(context,value){
        setTimeout(() => {
            context.commit("ADDNUMBER",value)
        },500)
    },
    addPersonWang(context,value){
        if(value.name.indexOf('王') === 0){
            context.commit('ADD_PERSON',value)
        }else{
            alert("请输入姓王的人")
        }
    }
}
//准备 mutations--用于操作数据
const mutations = {
    ADDNUMBER(state,value){
        state.totalNum += value
    },
    DECREMENT(state,value){
        state.totalNum -= value
    },
    ADD_PERSON(state,value){
        state.personList.unshift(value)
    }
}
//准备state--用于存储数据
const state = {
    totalNum:0,
    personList:[{id:"001",name:"张三"}]
}
​
//准备getters--用于计算state中的数据
const getters = {
    bigNum(){
        return state.totalNum * 10
    },
    firstPerson(){
        return state.personList[0]
    }
}
​
//创建并暴露 store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
})

新添加了一个 Persons组件,我们发现 store中的代码变得越来越多,所以我们可以把它们拆成两个store,把actions、mutations、state、getters 拆分成两部分,可以继续写在 index.js中,也可以分开写在两个文件中,在index.js 中引入这两个文件

count.js 如下:

const actions = {
    addNumOdd(context,value){
        if(context.state.totalNum % 2){
            context.commit("ADDNUMBER",value)
        }
    },
    addWait(context,value){
        setTimeout(() => {
            context.commit("ADDNUMBER",value)
        },500)
    },       
}
const mutations = {
    ADDNUMBER(state,value){
        state.totalNum += value
    },
    DECREMENT(state,value){
        state.totalNum -= value
    },
}
const state = {
    totalNum:0
}
const getters = {
    bigNum(){
        return state.totalNum * 10
    },
}
export default {
    namespaced:true,
    actions,
    mutations,
    state,getters
}

person.js 如下

const actions = {
    addPersonWang(context,value){
        if(value.name.indexOf('王') === 0){
            context.commit('ADD_PERSON',value)
        }else{
            alert("请输入姓王的人")
        }
    }
}
const mutations = {
    ADD_PERSON(state,value){
        state.personList.unshift(value)
    }
}
const state = {
    personList:[{id:"001",name:"张三"}]
}
const getters = {
    firstPerson(){
        return state.personList[0]
    }
}
export default {
    namespaced:true,
    actions,
    mutations,
    state,getters
}

在这两个新的js文件中,可以看到多了一个东西是 namespaced,就是命名空间,设置值为true。默认该值是false,如果不设置为 true,在组件中传入的配置名是识别不到的

在 index.js中

//该文件用于创建Vuex中最核心的Store
​
//引入Vue
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//使用vuex 插件
Vue.use(Vuex)
​
import countAbout from './count'
import personAbout from './person'
​
//创建并暴露 store
export default new Vuex.Store({
    modules:{
        countAbout,
        personAbout
    }
})

引入js文件,在 创建Store 实例时,在配置项配置 modules,里面的值是 引入的对象

 

在组件中使用分为两种情况

  • 使用mapxxx方法生成

    <script>
    import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'
    export default {
        name:'Counts',
        data(){
            return{
                selectNum:1
            } 
        },
        computed:{
            ...mapState('countAbout',['totalNum']),
            ...mapGetters('countAbout',['bigNum'])
        },
        methods:{
            ...mapActions('countAbout',['addNumOdd','addWait']),
            ...mapMutations('countAbout',['ADDNUMBER','DECREMENT'])
        }
    }
    </script>

    在引用 State、Getters、Actions、Mutations时,前面要传入一个参数,就是你在创建Store时配置的对象名,如果namespaced设置为false,那么这里传入的参数就识别不到,在 模板中只能用countAbout.xxx去使用数据了

  • 使用 this.$store.xxx

    <script>
    import {nanoid} from 'nanoid'
    export default {
        name:'Persons',
        data(){
            return{
                personName:''
            }
        },
        computed:{
            personList(){
                return this.$store.state.personAbout.personList
            },
            firstPerson(){
                return this.$store.getters['personAbout/firstPerson']
            },
            counts(){
                return this.$store.state.countAbout.totalNum
            }
        },
        methods:{
            addPerson(){
                const person = {id:nanoid(),name:this.personName}
                this.$store.commit('personAbout/ADD_PERSON',person)
                this.personName = ''
            },
            addPersonWang(){
                const person = {id:nanoid(),name:this.personName}
                this.$store.dispatch('personAbout/addPersonWang',person)
                this.personName = ''
            }
        }
    }
    </script>
    • 引入 state 时,使用 this.$store.state.personAbout.personList

    • 引入getters 时,使用 this.$store.getters['personAbout/firstPerson']

    • 调用dispatch时,this.$store.dispatch('personAbout/addPersonWang',person)

    • 调用commit时,this.$store.commit('personAbout/ADD_PERSON',person)

    getters、dispatch、commit 都需要使用 namespaced/xxx的方式

标签:const,value,state,store,Vuex,totalNum
From: https://www.cnblogs.com/wztblogs/p/18280087

相关文章

  • 【后台管理系统】Vuex实现简单组件间通信
    Vuex是组件间通信的一种方式,可以实现任意组件间的通信。官方文档:开始|Vuex(vuejs.org)https://vuex.vuejs.org/zh/guide/Vuex应用的核心其实就是一个共享的仓库store,在store.state中储存你需要修改的状态,在mutation中储存修改状态的方法,再使用commit提交修改方法。如果需......
  • Vuex模块化
    创建命名空间mian.jssrc/store/index.jssrc/store/getters.jssrc/store/modules各自管理仓库src/store/modules/testVuexModules.js命名空间模块组件内提交与获取Vuex的值:1.异步操作this.$store.dispatch2.同步操作this.$store.commit创建命名空间mian.jsim......
  • Vuex入门
    Vuex是什么?        Vuex是一个专为Vue.js应用程序开发的状态管理模式+库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。    可能有人不太理解这里的状态是什么,所谓“状态”,我们可以理解为数据,就是组......
  • (三十九)Vue之集中式的状态管理机制Vuex
    这里写目录标题概念vuex的核心概念State(状态)Getters(获取器)Mutations(突变)Actions(动作)搭建vuex环境基本使用getters的使用上一篇:(三十八)Vue之插槽Slots概念Vuex是一个专为Vue.js应用程序开发的状态管理模式。对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是......
  • [vue2]深入理解vuex
    本节内容概述初始化仓库定义数据访问数据修改数据处理异步派生数据模块拆分案例-购物车概述vuex是一个vue的状态管理工具,状态就是数据场景某个状态在很多个组件使用(个人信息)多个组件共同维护一份数据(购物车)优势数据集中式管理数据响应式变化初始化仓库......
  • 个人关于vuex的见解
    前言vuex是什么?Vuex是Vue.js的官方状态管理库,专为Vue.js应用程序设计,用于在复杂的前端应用中集中管理状态。Vuex的重要性集中管理:统一存储应用状态,简化复杂应用的状态逻辑。响应式更新:状态变更自动反映到所有依赖组件,保持UI与状态同步。预测性:状态变更通过mutatio......
  • 【vuex小试牛刀】
    了解vuex核心概念请移步https://vuex.vuejs.org/zh/#一、初始vuex#1.1vuex是什么就是把需要共享的变量全部存储在一个对象里面,然后将这个对象放在顶层组件中供其他组件使用父子组件通信时,我们通常会采用props+emit这种方式。但当通信......
  • 【前端每日基础】day42——关于 Vuex 共有几个属性,哪里可以书写同步任务,哪里可以书写
    Vuex是Vue.js的一个状态管理模式,它集中式地存储和管理应用的所有组件的状态。Vuex提供了以下几个核心属性,每个属性在状态管理中有不同的用途:Vuex共有的几个属性:State:用于存储应用的状态。可以通过this.$store.state或在组件中通过mapState辅助函数访问。Gette......
  • vue之vuex使用
    如图所示,它是一个程序里面的状态管理模式,它是集中式存储所有组件的状态的小仓库,并且保持我们存储的状态以一种可以预测的方式发生变化。对于可以预测,现在我不多做说明,相信在看完这篇文章之后,你就会有自己的理解。第一步,了解Vuex......
  • vue2组件中监听vuex中state的值
    vue2组件中监听Vuex 中state的值可以使用 mapState。官网链接:mapGetters辅助函数仅仅是将store中的getter映射到局部计算属性。Getter|Vuex(vuejs.org)参考文档: 监听Vuex中的数据变化-资深if-else侠-博客园(cnblogs.com)Vuex入门(2)——state,mapState,...ma......