Vue篇-05

发布于:2025-02-10 ⋅ 阅读:(39) ⋅ 点赞:(0)

5 vuex

5.1 vuex是什么

  • 概念:专门在 Vue 中实现集中式状态(数据)管理的一个Vue 插件,对 vue 应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。
  • Github 地址: https://github.com/vuejs/vuex

5.2 什么时候用

  • 多个组件依赖于同一状态
  • 来自不同组件的行为需要变更同一状态

5.3 求和案例

Count.vue:-纯vue版

<template>
  <div>
    <h1>当前求和为:{{sum}}</h1>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementOdd">当前求和为奇数再加</button>
    <button @click="incrementWait">等一等再加</button>
  </div>
</template>

<script>
export default {
  name:'Count',
  data(){
    return{
      n:1,//用户选择的数字
    sum:0//当前的和
    }
  },
  methods:{
    increment(){
      this.sum+=this.n
    },
    decrement(){
      this.sum-=this.n
    },
    incrementOdd(){
      if(this.sum%2){
        this.sum+=this.n
      }
    },
    incrementWait(){
      setTimeout(()=>{

      },500)
    }
  }
}
</script>

<style lang="css">
  button{
    margin-left: 5px;
  }
</style>

5.4 vuex原理

在vscode界面,使用npm i vuex@3安装第三个版本的适用于vue2的版本

5.5 搭建环境


1.创建文件:src/store/index.js

//引入vue核心库
import Vue from 'vue
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
//淮备actions对象一响应组件中用户的动作
const actions ={}
//推备mutations对象-修改state中的数据
const mutations ={}
//准备state对象-保存具体的数据
const state ={}
//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state
})

2.在 main.js 中创建vm时传入 store 配置项

//引入store
import store from './store
//创建vm
new Vue({
    el:'#app',
    render:h =>h(App),
    store
})

5.6 基本使用


1.初始化数据、配置 actions、配置mutations,操作文件 store.js
 

//引入vue核心库
import Vue from 'vue
//引入Vuex
import Vuex from 'vuex
//引用Vuex
Vue.use(Vuex)

const actions ={
    //响应组件中加的动作
    jia(context,value){
        // console.log('actions中的jia被调用了',ministore,value)
        context.commit('JIA',value)
    },
}

const mutations ={
    //执行加
    JIA(state,value){
        // console.log('mutations中的JIA被调用了',state,value)
        state.sum += value
    }
}

//初始化数据
const state = {
    sum:0
}

//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
})

2.组件中读取vuex中的数据:$store.state.sum
3.组件中修改vuex中的数据:$store.dispatch('action中的方法名',数据)$store.commit('mutations中的方法名',数据)


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

getters的使用
1.概念:当state中的数据需要经过加工后再使用时,可以使用getters加工
2.在 store.js 中追加 getters 配置

const getters ={
    bigSum(state){
        return state.sum*10
    }
}

//创建并暴露store
export default new Vuex.Store({
    getters
})

3.组件中读取数据:$store.getters.bigSum 

5.7 四个map方法的使用

1.mapstate方法:用于帮助我们映射 state 中的数据为计算属性

computed:{
    //借助mapstate生成计算属性:sum、schoo1、subject(对象写法)
    ...mapState({sum:'sum',school:'school',subject:'subject'})
    //借助mapState生成计算属性:sum、schoo1、subject(数组写法)
    ...mapState(['sum','school','subject'])
},

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

computed:{
    //借助mapGetters生成计算属性:bigSum(对象写法)
    ...mapGetters({bigSum:'bigSum'})
    //借助mapGetters生成计算属性:bigSum(数组写法)
    ..mapGetters(['bigSum'])
},

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

methods:{
    //靠mapActions生成:incrementOdd、incrementWait(对象形式)
    ...mapActions({incrementOdd:'jia0dd',incrementWait:'jiaWait'})
    //靠mapActions生成:incrementOdd、incrementWait(数组形式)
    ...mapActions(['jia0dd','jiaWait'])
}

4.mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数

methods :{
    //靠mapActions生成:increment、decrement(对象形式)
    ...mapMutations({increment:'JIA',decrement:"JIAN'})
    //靠mapMutations生成:JIA、JIAN(对象形式)
    ...mapMutations(['JIA','JIAN']),
}

备注:mapActionsmapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。 

5.8 多组件共享数据

 就是各个组件都能拿到state里的数据,然后用来用去了,很方便

5.9 Vuex模块化+命名空间(项目常用)

如果我们写的state,actions什么的是服务于多个种类的,比如有管加法的,有管人员的,这样放到一起很乱,所以可以把它们拆开 

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

使用方式:

可以都写到index.js里,也可以每个命名空间分别拆成多个js文件

const countAbout = {
namespaced:true,//开启命名空间
state:{x:1},
mutations: { ... },
actions: { ... },
getters: {...}
}
}

const personAbout = {
namespaced:true,//开启命名空间
state:{ ... },
mutations: { ... },
actions: { ... }
}

const store = new Vuex.Store({
modules: {
 countAbout,
 personAbout
}
})

1、开启命名空间后,组件中读取state数据 

//方式一:自己直接读取
this.$store.state.personAbout.list
//方式二:借助mapState读取:
...mapState('countAbout',['sum','school','subject']), 
// 前边加个参数,意思是读取countAbout 里面的 sum,school.....

2、开启命名空间后,组件中读取getters数据 

//方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName'] //很奇葩
//方式二:借助mapGetters读取:
...mapGetters('countAbout',['bigSum'])  

3、开启命名空间后,组件中调用dispatch

如果不写namespaced则直接写addPersonWang就可以,但是开启了命名空间,必须要加上这个名字在前边,否则会报[vuex] unknown action type: addPersonWang的错误,而且前边这个名字必须和Vuex.Store({})配置项中的名字一致。

//方式一:自己直接dispatch
this.$store.dispatch('personAbout/addPersonWang',person)
//方式二:借助mapActions:
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})

4、开启命名空间后,组件中调用commit

//方式一:自己直接commit
this.$store.commit('personAbout/ADD_PERSON',person)
//方式二:借助mapMutations:
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),

 完整代码:

1、index.js

//引入Vue
import Vue from 'vue';
//引入Vuex
import Vuex from 'vuex';//引入插件并使用插件
Vue.use(Vuex);

//关于计数的相关配置
import countAbout from './Count'

//关于人员的相关配置
import personAbout from './Person'


//创建并导出store
export default new Vuex.Store({
    modules: {
        countAbout: countAbout,
        personAbout  //重名简写 
    }
});

 2、Count.js

export default {
    namespaced: true,
    state: {
        sum: 0,  //初始化数据
        school: '杭州',
        subject: '前端',
    },
    getters: {
        bigSum(state) {
            return state.sum * 10;
        }
    },
    actions: {
        oddAdd(context, value) {
            //第一个参数是浓缩版的$store,方便你在这里调用commit把东西给mutations
            //第二个参数是传过来的数据
            context.commit('JIA', value);
        },
        waitAdd(context, value) {
            setTimeout(() => {
                context.commit('JIA', value);
            }, 1000);
        },
    },
    mutations: {
        JIA(state, value) {
            //第一个参数是state对象,第二个参数是传过来的数据
            console.log('mutations中的JIA被调用了 ', state, value);
            state.sum += value;
        },
        JIAN(state, value) {
            state.sum -= value;
        },
    }
}

3、Count.vue

<template>
    <div>
        <h1>当前求和为:{{  sum  }}</h1>
        <h2>当前求和放大十倍后为:{{  bigSum  }}</h2>
        <h3>我在{{  school  }}学习{{  subject  }}</h3>
        <select v-model.number="addnum">
            <option value="1" checked>1</option><!-- 不写冒号就是字符串但可以v-model.number -->
            <option value="2">2</option> <!-- 不写冒号就是字符串但可以v-model.number -->
            <option value="3">3</option> <!-- 不写冒号就是字符串但可以v-model.number -->
        </select>
        <button @click="JIA(addnum)">+</button>
        <button @click="JIAN(addnum)">-</button>
        <button @click="oddAdd(addnum)">当前求和为奇数再加</button>
        <button @click="waitAdd(addnum)">等1秒再加</button>

        <h2 style="color:red">Count里边读personList</h2>
        <ul style="color:red">
            <li v-for="p in personList" :key="p.id">{{  p.name  }}</li>
        </ul>
    </div>
</template>

<script>
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex';
export default {
    name: 'Count',
    data() {
        return {
            addnum: 1
        }
    },
    computed: {
        personList() {
            return this.$store.state.personAbout.personList;
        },
        ...mapState('countAbout', ['sum', 'school', 'subject']),
        ...mapGetters('countAbout', { bigSum: 'bigSum' }),
    },
    methods: {
        ...mapMutations('countAbout', ['JIA', 'JIAN']),
        ...mapActions('countAbout', { oddAdd: 'oddAdd', waitAdd: 'waitAdd' }),
    },
    mounted() {
        console.log(this.$store)
    }
};
</script>

 4、Person.js

import axios from 'axios';
import { nanoid } from 'nanoid';
export default {
    namespaced: true,
    state: {
        personList: [
            { id: 1, name: 'zzy' }
        ]
    },
    getters: {
        firstPersonName(state) {
            return state.personList[0].name;
        }
    },
    actions: {
        addPersonHan(context, value) {
            if (value.name.indexOf('韩') === 0) {
                context.commit('ADD_PERSON', value);
            } else {
                alert('添加的人不姓韩!');
            }
        },
        //发送ajax请求拿到名字
        addPersonServer(context) {
            axios.get('http://api.uixsj.cn/hitokoto/get?type=social').then(
                response => {
                    context.commit('ADD_PERSON', { id: nanoid(), name: response.data });
                },
                error => {
                    console.log(error.message);
                }
            )
        }
    },
    mutations: {
        ADD_PERSON(state, value) {
            state.personList.unshift(value);
        }
    }
}

5、Person.vue

<template>
    <div>
        <h2>Person里边读personList</h2>
        <input type="text" placeholder="请输入名字" v-model="name">
        <button @click="addPerson">添加</button>
        <button @click="addPersonHan">添加一个姓韩的人</button>
        <button @click="addPersonServer">随机添加一个名字</button>
        <h2>第一个人的名字:{{  firstPersonName  }}</h2>
        <ul>
            <li v-for="p in personList" :key="p.id">{{  p  }}</li>
        </ul>
        <h2 style="color:red">Person里读sum:{{  add  }}</h2>
    </div>
</template>

<script>
import { nanoid } from 'nanoid';
export default {
    name: 'Person',
    data() {
        return {
            name: ''
        }
    },
    computed: {
        personList() {
            return this.$store.state.personAbout.personList;
        },
        add() {
            return this.$store.state.countAbout.sum;
        },
        firstPersonName() {
            return this.$store.getters['personAbout/firstPersonName'];
        }
    },
    methods: {
        addPerson() {
            const personObj = { id: nanoid(), name: this.name };
            this.$store.commit('personAbout/ADD_PERSON', personObj);
            this.name = '';  //添加完了输入框置空
        },
        addPersonHan() {
            const personObj = { id: nanoid(), name: this.name };
            this.$store.dispatch('personAbout/addPersonHan', personObj);
        },
        addPersonServer() {
            this.$store.dispatch('personAbout/addPersonServer');
        }
    },
};
</script>

 注意:只有指定相应的模块名才能找到对应的数据和方法(前提是模块开启了命名空间)

其中的部分笔记引用下面的文章

Vue2(十二):Vuex环境搭建、Vuex工作原理、几个配置项、多组件共享数据、Vuex模块化_vue2 yarn安装vuex-CSDN博客


网站公告

今日签到

点亮在社区的每一天
去签到