cometang前端技术博客 cometang前端技术博客
首页
  • html5
  • JavaScript
  • ES6
  • Vue
  • 微信小程序
  • react
  • react上手教程
  • 前端框架
  • 大神之路
  • 面试汇总
  • Node
  • PHP
  • Go语言
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

cometang

永远相信技术的力量
首页
  • html5
  • JavaScript
  • ES6
  • Vue
  • 微信小程序
  • react
  • react上手教程
  • 前端框架
  • 大神之路
  • 面试汇总
  • Node
  • PHP
  • Go语言
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • ES6

  • vue

    • vue基础详解
    • vue组件与路由
    • 组件通信与插槽
    • MVC与MVVM
    • vuex状态管理
      • 1.前言
      • 2.vue 组件传值回顾
        • 2.1 父传子 动态属性+props
        • 2.2 子传父 $emit+自定义事件
        • 2.3 中央事件总线 $bus eventBus
        • 2.4 祖宗孙子传值: provide+ inject
        • 2.5 中间商:父亲组件带动态属性 $attrs $listeners
      • 3.Vuex 状态管理仓库
      • 4 获取 state 中的数据
      • 5.mutations 修改数据的方法
        • 5.1 在组件中直接修改值
        • 5.2 定义mutations的方法 用来修改数据
      • 6. actions 异步修改数据
      • 7.修饰器:Getters
      • 8. 模块 Module
      • 9.Vuex 数据持久化 插件
    • TypeScript基础
    • vue进阶
    • Vue2 装饰器与TS结合
    • Vue3.2 语法基础
    • Vue3.2项目架构
    • vue进阶-keepalive
    • vue2配置-环境变量-响应式-proxy-mock
    • vite打包工具
  • h5

  • JavaScript

  • 前端框架

  • react

  • 大神之路

  • 微信小程序

  • 面试题汇总

  • react轻松上手教程

  • 前端
  • vue
cometang
2022-06-04
目录

vuex状态管理

    https://juejin.cn/post/6928468842377117709
1

# 1.前言

官网地址:https://vuex.vuejs.org/zh/

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

作用: 将整个系统中所有的状态(需要跨页面 跨组件传值的变量)都存储到vuex仓库中,实现任意组件都可以对该数据进行存取操作。

# 2.vue 组件传值回顾

  • 父传子 动态属性+props
  • 子传父 $emit+自定义事件
  • 中央事件总线 Vue.prototype.$bus=new Vue() +$emit+$on
  • 祖宗孙子传值: provide+ inject

# 2.1 父传子 动态属性+props

父组件

<子组件名  title="你好啊"  :age="20"></子组件名>
1

子组件

通过props 接收后, 直接用 this.变量使用

props:{
    title:{
        type:String,
        default:'标题'
    },
    age:{
        type:Number,
        default:0
    },   
}
1
2
3
4
5
6
7
8
9
10

# 2.2 子传父 $emit+自定义事件

父组件

<子组件名 @自定义事件类型名="执行函数"></子组件名>
1
methods:{
    执行函数(data){
        //data 就是 子组件传递给父组件的数据
    }
}
1
2
3
4
5

子组件

this.$emit('自定义事件类型名',传递的数据)
1

# 2.3 中央事件总线 $bus eventBus

在同一个页面组件中 的所有子组件可以任意传递数据

main.js 全局挂载 一个新的vue实例对象作为 中央

Vue.prototype.$bus = new Vue()
1

发送数据的组件

//发送数据
this.$bus.$emit('自定义事件类型',发送的数据)
1
2

接收数据的组件

接收数据的组件可以在created 生命周期中 监听该自定义事件,如果被触发就可以拿到数据

this.$bus.$on('自定义事件类型',(data)=>{
    //data 就是 拿到的数据
})
1
2
3

# 2.4 祖宗孙子传值: provide+ inject

优:祖宗节点定义好数据,所有的孙子组件 都可以使用该数据 非常方便

缺:只能传递一个 固定值下去,没有响应式(子组件修改了该数据,祖宗节点的数据并不会发生变化)

祖宗组件

  //   祖宗注入依赖
  provide: {
    name: '你好呀',
  },
1
2
3
4
 //   祖宗注入依赖
  provide() {
    return {
      name: "你好呀",
    };
  },
1
2
3
4
5
6

孙子组件

   export default {
        inject:['name'],
        mounted(){
            //可以获取和使用
            console.log(this.name);
            //不能修改---报错
            this.name = '我是孙子组件'
        }
    }
1
2
3
4
5
6
7
8
9

# 2.5 中间商:父亲组件带动态属性 $attrs $listeners

通过属性传值:可以快速实现 祖宗==>孙子 孙子==>祖宗【父亲组件只是一个中间商 负责 转发数据和转发事件】

爷爷组件

<template>
  <div>
      我是爷爷组件
         <button @click="title='我是爷爷组件的新数据'">点击修改数据</button>
          <hr />
         <father :title="title" @change="getData"></father>
  </div>
</template>

<script>
import Father from './components/AppFather.vue'
export default {
  data() {
    return {
      title: "我是爷爷组件的数据",
    };
  },
  methods:{
      //根据自定义数据 获取孙子组件的传递数据
      getData(data){
        console.log(data);
      }
  },
  components: {
    Father,
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

父亲组件

父亲组件 通过$attrs 将获取到的上一层的数据 传递给 下一级

父亲组件 通过 $listeners 将获取到的自定义事件 传递给上一级 触发

<template>
    <div>
        父亲组件:
        <hr>
        <grand-son v-bind="$attrs" v-on="$listeners" ></grand-son>
    </div>
</template>

<script>
  import GrandSon from './GrandSon.vue'
    export default {
        components:{
            GrandSon
        }
    }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

孙子组件

<template>
  <div>
    我是孙子组件:
    <p>{{ title }}</p>
    <button @click="changeData">回传数据给祖宗</button>
  </div>
</template>

<script>
export default {
  props: {
      // 在爷爷组件中传递过来的属性
    title: { 
        type:String,
        default:'标题'
     },
  },
  methods:{
      changeData(){
          let data ={msg:"我是孙子组件回传的数据"}
          this.$emit('change',data)
      }
  },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 3.Vuex 状态管理仓库

  • 安装vuex
yarn add vuex@3.6.2   
//或
npm i vuex@3.6.2    
1
2
3
  • 创建vuex 的仓库文件 src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

//注册插件 
Vue.use(Vuex);
//根据vuex的store 生成实例对象 
const store = new Vuex.Store({
    //存数据的仓库
    state:{
        name:'comentang'
    },
    //修改仓库中数据的同步方法
    mutations:{

    },
    //调用 同步方法 实现异步修改仓库中的数据
    actions:{

    }
})
//暴露生成的vuex实例
export default store;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  • main.js 进行导入和挂载
import store from './store'

new Vue({
  router,
  store,  //将store 实例挂载到vue顶级实例对象上
  render: h => h(App)
}).$mount('#app')

1
2
3
4
5
6
7
8

# 4 获取 state 中的数据

state:{
 	name:"cometnag"     
 }
1
2
3
  • 直接通过实例对象层级查找

缺点:每次改变都需要使用该语句进行重新获取,代码太冗长

this.name = this.$store.state.name     //cometang
1
  • 通过 计算属性 获取值

优点:如果仓库中的数据发生了变化,computed 会自动触发,重新更新值

computed:{
    nameData(){
        return this.$store.state.name;
    }
}
1
2
3
4
5
  • 通过计算属性 + 对象解构获取

将mapState 对象解构出来直接放到 computed中

优点:使用简便,推荐此方法

import {mapState} from 'vuex'

computed:{
    ...mapState(['name'])
}
1
2
3
4
5

# 5.mutations 修改数据的方法

# 5.1 在组件中直接修改值

直接通过实例对象层级赋值

缺点:任何组件任何时候都可以修改这个数据,给数据维护带来了不稳定性。

vuex官网页非常明确的指出,修改vuex仓库中的数据必须使用 vuex中定义的方法。

低版本的vuex 数据会修改成功 但是控制台会有报错提示。

this.$store.state.name = '新数据'
1

# 5.2 定义mutations的方法 用来修改数据

const store = new Vuex.Store({
    //存数据的仓库
    state:{
        name:'comentang'
    },
    //修改仓库中数据的同步方法
    mutations:{
        changeName(state,newData){
            state.name = newData
        }
    },
})
1
2
3
4
5
6
7
8
9
10
11
12
  • 在组件中 调用该方法 实现修改数据
this.$store.commit('changeName',新数据)
1
  • methods+解构的方式 【推荐】
import { mapMutations } from 'vuex';
methods:{
     // 注意,mapMutations是解构到methods里面的,而不是计算属性了
    ...mapMutations(['changeName']),
     //使用方法和methods中的函数 一致。    
     // this.changeName(新数据) 修改数据 
}
1
2
3
4
5
6
7

# 6. actions 异步修改数据

定义actions 异步操作中 通过上下文 调用同步方法 修改数据

 //调用 同步方法 实现异步修改仓库中的数据
    actions:{
        //1s之后 通过上下文 调用同步方法修改数据
        setAsyncData(context,newData){
            return new Promise(resolve=>{
                setTimeout(()=>{
                    context.commit('changeName',newData);
                    resolve();
                },1000)
            })
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
  • 在组件中 调用该方法 实现修改数据
   let res = await  this.$store.dispatch('setAsyncData',this.title)
1
  • methods+解构的方式 【推荐】
import { mapActions } from 'vuex';
methods:{
     // 注意,mapActions是解构到methods里面的,而不是计算属性了
        ...mapActions(['setAsyncData']),
   	    let res= await this.setAsyncData(this.title)
}
1
2
3
4
5
6

# 7.修饰器:Getters

获取数据时 统一对该数据进行处理之后 再返回新数据

特点:必须要有return 返回新数据 ,调用时不需要传参数

定义修饰器

 getters:{
        updateName(state){
            return '你好呀'+state.name;    
        }
    }
1
2
3
4
5
  • 组件中直接使用 获取数据
 this.$store.getters.updateName
1
  • 通过computed 解构函数使用
import {mapGetters} from 'vuex'
 computed:{
    ...mapGetters(['updateName'])
  },
  created() {
    //取值
    this.updateName1 = this.updateName
  }
1
2
3
4
5
6
7
8

# 8. 模块 Module

假设一个项目功能比较复杂,在vuex中存储的数据非常多,设置出现了同名的情况,这种时候就不能直接写到一个store 文件中了,应该根据不同的功能模块 对 该store文件进行拆分。

思路:写独立的js文件 将 5个核心配置写入一个对象 并 暴露出去,导入到总的store里面的modules里面

现有模块: 用户模块users 商品模块 goods

src/store/index.js  #总的vuex主模块
src/store/users.js   #用户模块
src/store/goods.js  #商品模块
1
2
3
//index.js
import Vue from 'vue'
import Vuex from 'vuex'

// 导入子模块  
import users from './users'
import goods from './goods'


//注册插件 
Vue.use(Vuex);
//根据vue的store 生成实例对象 
const store = new Vuex.Store({
    state: {
        name: '我是主模块的cometang'
    },
    mutations: {
    },
    actions: {
    },
    getters: {
    },
    //模块
    modules: {
        users, goods
    }
})
//暴露生成的vuex实例
export default store;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// goods
const goods = {
    namespaced: true,
    state:{
        goodsName:'我是goods的name'
    },
    mutations:{

    },
    actions:{

    },
    getters:{

    }
}
export default goods
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//users
const users = {
    namespaced: true,
    state: {
        userName: '我是userjs的name'
    },
    mutations: {

    },
    actions: {

    },
    getters: {

    }
}
export default users
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

注意:使用了模块化和命名空间之后对于子模块中的数据,方法的调用 不再建议使用 解构赋值快速复制的方式进行.

原因:本来命名空间打开就是为了区分各个不同的模块,如果用解构的方式,可能会造成数据变量名 方法名重名使用的风险。

  • 使用方式
//获取数据
this.$store.state.users.userName;
//获取Getters 修饰器的数据
this.$store.getters.users.userName;
//调用同步方法
this.$store.commit('模块名/mutations的方法名',传递的数据)
// 调用异步方法
this.$store.dispatch('模块名/actions的方法名',传递的数据)
1
2
3
4
5
6
7
8
  • 解构使用

特点:一个组件中 只能解构一个模块的数据 和方法

import { mapState,mapMutations,mapActions,mapGetters } from 'vuex';
  computed:{
    ...mapState('users',['userName']),     //this.userName
    ...mapGetters('users',['newUserName'])  //this.newUserName
  },
  methods:{
    ...mapMutations('users',['updateName']), //this.updateName(数据)
    ...mapActions('users',['asyncUpdateName'])//this.asyncUpdateName(数据)
  },
1
2
3
4
5
6
7
8
9

# 9.Vuex 数据持久化 插件

系统中经常需要将很多数据 存储起来 以后仍然可以使用(关闭浏览器之后 重新打开仍然可用)

思路一: 在所有的state 中 增加循环,把数据全部存储到本地存储localStorage之中。

思路二:使用数据持久化的插件

npm install vuex-persistedstate   
或
yarn add vuex-persistedstate 
1
2
3
//数据持久化插件导入
import persistedState from 'vuex-persistedstate'

//根据vue的store 生成实例对象 
const store = new Vuex.Store({
    state: {
    },
    mutations: {
    },
    actions: {
    },
    getters: {
    },
    //模块
    modules: {
    },
    plugins: [persistedState()] //添加插件
    
})
//暴露生成的vuex实例
export default store;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
编辑 (opens new window)
上次更新: 2022/06/10, 01:34:10
MVC与MVVM
TypeScript基础

← MVC与MVVM TypeScript基础→

最近更新
01
go语言基础
07-13
02
《react上手教程》- 基础语法
07-13
03
redux-redux toolkit-状态管理
03-18
更多文章>
Theme by Vdoing | Copyright © 2019-2023

cometang | 唐世杰 渝ICP备18015657号-2

  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式