vuex的学习

发布于:2023-01-13 ⋅ 阅读:(631) ⋅ 点赞:(0)

目录

一、vuex

1.定义

2.安装

二、store创建

1.定义

2.结构

3.引入store

三、状态的核心概念

1. state

2. actions

3. mutations

4. getters

5.数据映射

6. 案列示例

四、模块化编码(modules)


一、vuex

1.定义

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

 原理图:

State | VuexVue.js 的中心化状态管理方案https://vuex.vuejs.org/zh/guide/state.html

vuex多应用于多个组件应用与同一个状态,多个组件变更同一状态。

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

什么是“状态管理模式”?

这个状态自管理应用包含以下几个部分:

  • 状态,驱动应用的数据源;
  • 视图,以声明方式将状态映射到视图;
  • 操作,响应在视图上的用户输入导致的状态变化。

以下是一个表示“单向数据流”理念的简单示意:

但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:

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

2.安装

npm i vuex@3        注释:@3是版本号,vue2用vuex@3版本,vue3用4版本

二、store创建

1.定义

概念:每一个Vuex应用的核心就是Store(仓库),我们可以说Store是一个容器,它包含着你的应用中大部分的状态 (state)。但Store里面的状态与单纯的全局变量是不一样的,无法直接改变Store中的状态。想要改变状态需通过mutation去修改。

Vuex 和单纯的全局对象有以下两点不同:

  1. Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

  2. 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

2.结构

创建文件夹store与src根目录下,建立index.js。需包含actions,mutations,state结构如下:

import Vue  from 'vue'        // 引入vue

import Vuex from 'vuex'        // 引入vuex

Vue.use(Vuex)         // 应用vue插件

// actions响应组件中的动作

const actions = { }

// mutations操作数据state

const mutations = { }

// 准备state存储数据

const state = {

   //状态对象

}

 

//想要对状态有要进一步的加工时可以用到

//getters  从 store 中的 state 中派生出一些状态

const getters={

    randmajor(state){

        return state.major+Math.ceil(Math.random()*9) + Math.ceil(Math.random()*9) + Math.ceil(Math.random()*9);

    }

}

 

// 创建store并导出

const store = new Vuex.Store({

              actions,

              mutations,

              state,

              getters

})

//默认导出store

export default store

3.引入store

在main.js中引入store,全局组件都可以使用vuex。

import store from './store'

new Vue({

  render: h => h(App),

  store,

}).$mount('#app')

三、状态的核心概念

1. state

state是状态数据,可以通过this.$store.state来直接获取状态,也可以利用vuex提供的mapState辅助函数将state映射到计算属性(computed)中去。

示例:

1. index.js

const state = {

    //状态对象

    name:'2209',

    major:'web前端',

 }

2. 两个组件中的写法

1)插值引用:{{$store.state.name}}

<h2>班级:{{$store.state.name}},专业:{{$store.state.major}}</h2>

2)在计算属性中写法

<h2>班级:{{name}},专业:{{major}}</h2>

computed:{

        name(){

            return this.$store.state.name;

        },

        major(){

            return this.$store.state.major;

        }

}

 

3)数据映射写法

<h2>班级:{{myname}},专业:{{mymajor}}</h2>

import {mapState} from 'vuex'

computed:{

        // 当计算属性的名称与vuex一致的时候 用数组形式

        // ...mapState(["name","major"]),

        // 当计算属性的名称与vuex不一致的时候 用对象形式

        ...mapState({myname:"name",mymajor:"major"}),

}

2. actions

Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。

// actions响应组件中的动作

//context 上下文,value组件传递过来的值

//可以包含定时器,ajax代码,有业务逻辑使用action,无业务逻辑直接使用mutations

//index.js中

const actions = {

    editwait(context,value){

        setTimeout(()=>{

            context.commit('editmajor',value);

        },3000)

    }

}

 在组件中使用: $store.dispatch('对应的 action 回调名') 触发

<button @click="editwait('java')">等3s更改专业</button>

 

methods:{

        editwait(str){

            this.$store.dispatch('editwait',str);

        }

    }

用数据映射触发

<button @click="editwait('java')">等3s更改专业</button>

import {mapActions } from 'vuex'

methods:{

       ...mapActions(['editwait']),

    }

3. mutations

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。

index.js:

// mutations操作数据state

const mutations = {

    editname(state,value){

        state.name=value;

    },

    editmajor(state,value){

        state.major=value;

    },

}

 组件中触发

<button @click="editname('2209班')">修改班级</button>

<button @click="editmajor('vue')">修改专业</button>

 

methods:{

        editname(){

            this.$store.commit('editname','2209班')

        },

        editmajor(){

            this.$store.commit('editmajor','vue')

        },

    }

此时的mutations 无业务逻辑,就是更改状态。 

数据映射方法:

<button @click="editname('2209班')">修改班级</button>

<button @click="editmajor('vue')">修改专业</button>

 

import {mapActions } from 'vuex'

methods:{

        ...mapActions(['editwait']),

    }

4. getters

有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数,也就是对状态在加工:

index.js:

//getter   从 store 中的 state 中派生出一些状态

const getters={

    randmajor(state){

        return state.major+Math.ceil(Math.random()*9) + Math.ceil(Math.random()*9) + Math.ceil(Math.random()*9);

    }

}

组件中调用数据:

 <h3>专业+随机数:{{randmajor}}</h3>

 

computed:{

         randmajor(){

             return this.$store.getters.randmajor;

         }

    },

 数据映射方法:

 <h3>专业+随机数:{{randmajor}}</h3>

 

import {mapGetters } from 'vuex'

computed:{

        ...mapGetters(['randmajor']),

    },

5.数据映射

三点运算符的形式书写

 mapMutations和mapActions

借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)

mapState和mapGetters:

mapState(mapGetters)生成计算属性,从state中读取状态(对象形式)

6. 案列示例

index.js部分

//需包含actions,mutations,state
// 引入vue
import Vue  from 'vue'

// 引入vuex
import Vuex from 'vuex'

// 应用vue插件
Vue.use(Vuex)

//1
// 准备state存储数据
const state = {
    //状态对象
    name:'2209',
    major:'web前端',
 }
 
// actions响应组件中的动作   可以包含任意异步操作
const actions = {
    editwait(context,value){
        setTimeout(()=>{
            context.commit('editmajor',value);
        },3000)
    }
}

// mutations操作数据state
const mutations = {
	editname(state,value){
        state.name=value;
    },
    editmajor(state,value){
        state.major=value;
    },
}

//getter   从 store 中的 state 中派生出一些状态
const getters={
    randmajor(state){
        return state.major+Math.ceil(Math.random()*9) + Math.ceil(Math.random()*9) + Math.ceil(Math.random()*9);
    }
}



//创建store并导出
const store = new Vuex.Store({
	actions,
	mutations,
	state,
    getters
})
//默认导出store
export default store

组件1

 

<template>
    <div>
        <!-- <h2>班级:{{$store.state.name}},专业:{{$store.state.major}}</h2> -->
        <!-- <h2>班级:{{name}},专业:{{major}}</h2> -->
        <h2>班级:{{myname}},专业:{{mymajor}}</h2>
        <h3>专业+随机数:{{randmajor}}</h3>
        <p>姓名:张三,年龄:18</p>
        <button @click="editname('2209班')">修改班级</button>
        <button @click="editmajor('vue')">修改专业</button>
        <button @click="editwait('java')">等3s更改专业</button>
    </div>
</template>
<script>
import {mapActions, mapGetters, mapMutations, mapState, } from 'vuex'
export default {
    name:'ZhangSan',
    computed:{
        // name(){
        //     return this.$store.state.name;
        // },
        // major(){
        //     return this.$store.state.major;
        // }

        // 当计算属性的名称与vuex一致的时候 用数组形式
		// ...mapState(["name","major"]),
		// 当计算属性的名称与vuex不一致的时候 用对象形式
        ...mapState({myname:"name",mymajor:"major"}),

        // randmajor(){
        //     return this.$store.getters.randmajor;
        // }
        ...mapGetters(['randmajor']),
    },
    methods:{
        editname(){
            this.$store.commit('editname','2209班')
        },
        editmajor(){
            this.$store.commit('editmajor','vue')
        },
        ...mapMutations(['editname','editmajor']),

        // editwait(str){
        //     this.$store.dispatch('editwait',str);
        // }
        ...mapActions(['editwait']),

    }
}
</script>
<style scoped>

</style>

组件2

<template>
    <div>
        <!-- <h2>班级:{{$store.state.name}},专业:{{$store.state.major}}</h2> -->
        <!-- <h2>班级:{{name}},专业:{{major}}</h2> -->
        <h2>班级:{{myname}},专业:{{mymajor}}</h2>
        <h3>专业+随机数:{{randmajor}}</h3>
        <p>姓名:李四,年龄:20</p>
    </div>
</template>
<script>
import {mapState,} from 'vuex'
export default {
    name:'LiSi',
    computed:{
        // name(){
        //     return this.$store.state.name;
        // },
        // major(){
        //     return this.$store.state.major;
        // }

        // 当计算属性的名称与vuex一致的时候 用数组形式
		// ...mapState(["name","major"]),
		// 当计算属性的名称与vuex不一致的时候 用对象形式
        ...mapState({myname:"name",mymajor:"major"}),
        randmajor(){
            return this.$store.getters.randmajor;
        }

    }
}
</script>
<style scoped>

</style>

 整体效果:

 共享状态,通过store把数据共享给两个组件,所以组件里的数据状态会随store里的数据变化而变化

四、模块化编码(modules)

Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割在模块中使用:namespaced: true, 命名空间,添加之后,当前模块下的标识符可以和其它模块相同,用于解决不同模块的命名冲突问题

就上面一个示例来进行模块化编码:

index,js部分

//需包含actions,mutations,state
// 引入vue
import Vue  from 'vue'

// 引入vuex
import Vuex from 'vuex'

// 应用vue插件
Vue.use(Vuex)


const Persons={
    namespaced:true,
    state:{
        //状态对象
        name:'2209',
        major:'web前端',
    },
    actions:{
        editwait(context,value){
            setTimeout(()=>{
                context.commit('editmajor',value);
            },3000);
        }
    },
    mutations:{
        editname(state,value){
            state.name=value;
        },
        editmajor(state,value){
            state.major=value;
        },
    },
    getters:{
        randmajor(state){
            return state.major+Math.ceil(Math.random()*9) + Math.ceil(Math.random()*9) + Math.ceil(Math.random()*9);
        }
    }
}


//创建store并导出
const store = new Vuex.Store({
	modules:{
        Persons
    }
})
//默认导出store
export default store

组件1

<template>
    <div>
        <!-- <h2>班级:{{$store.state.name}},专业:{{$store.state.major}}</h2> -->
        <!-- <h2>班级:{{name}},专业:{{major}}</h2> -->
        <h2>班级:{{myname}},专业:{{mymajor}}</h2>
        <h3>专业+随机数:{{randmajor}}</h3>
        <p>姓名:张三,年龄:18</p>
        <button @click="editname('2209班')">修改班级</button>
        <button @click="editmajor('vue')">修改专业</button>
        <button @click="editwait('java')">等3s更改专业</button>
    </div>
</template>
<script>
import {mapActions, mapGetters, mapMutations, mapState, } from 'vuex'
export default {
    name:'ZhangSan',
    computed:{
        ...mapState('Persons',{myname:"name",mymajor:"major"}),
        ...mapGetters('Persons',['randmajor']),
    },
    methods:{
        ...mapMutations('Persons',['editname','editmajor']),
        ...mapActions('Persons',['editwait']),
    }
}
</script>
<style scoped>

</style>

组件2

<template>
    <div>
        <!-- <h2>班级:{{$store.state.name}},专业:{{$store.state.major}}</h2> -->
        <!-- <h2>班级:{{name}},专业:{{major}}</h2> -->
        <h2>班级:{{myname}},专业:{{mymajor}}</h2>
        <h3>专业+随机数:{{randmajor}}</h3>
        <p>姓名:李四,年龄:20</p>
    </div>
</template>
<script>
import {mapState,mapGetters} from 'vuex'
export default {
    name:'LiSi',
    computed:{
        ...mapState('Persons',{myname:"name",mymajor:"major"}),
        ...mapGetters('Persons',['randmajor']),
    }
}
</script>
<style scoped>

</style>

代码运行效果和上例一样


网站公告

今日签到

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