Vue全家桶(三):Vuex状态管理(State、Getters、Mutations、Actions)

news/2024/10/29 1:21:21/

目录

  • Vuex
    • 1. 理解Vuex
      • 1.1 组件之间共享数据的方式
      • 1.2 Vuex是什么
      • 1.2 什么时候使用Vuex
      • 1.3 Vuex的工作原理图
    • 2 使用Vuex
      • 2.1 搭建Vuex环境
    • 2.2 Vuex基本使用
      • 2.2.1 State
      • 2.2.2 Getters
      • 2.2.3 Mutations
      • 2.2.4 Actions
      • 2.2.5 Modules 模块化+命名空间
    • 3 求和案例
      • 3.1 使用纯vue编写
      • 3.2 使用Vuex编写
        • 3.2.1 原始写法
        • 3.2.2 用mapXXX优化后
        • 3.2.2 多组件共享数据
        • 3.2.3 模块化优化后
    • 4 求和案例2
      • 4.1 props传递值
      • 4.2 Vuex的state传递
      • 4.3 Matuations来修改状态
      • 4.4 Mutations带参数传递修改状态
    • 5 多组件共享数据案例

Vuex

1. 理解Vuex

1.1 组件之间共享数据的方式

父向子传值:v-bind 属性绑定
子向父传值:v-on 事件绑定

兄弟组件之间共享数据: EventBus(事件总线)
$on 接收数据的那个组件
$emit 发送数据的那个组件

1.2 Vuex是什么

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

Vuex Github: https://github.com/vuejs/vuex

  1. 全局事件总线和Vuex对比
    Vuex是什么
    在这里插入图片描述

1.2 什么时候使用Vuex

处理大量的需要在组件间传递的数据,直接定义一个全局的data属性保存就行了。
如果我们的页面比较简单,切记千万不要没事找事引入Vuex,我们使用Vuex是因为项目变得复杂之后,有很多数据需要在父组件、子组件和孙组件之间传递,处理起来很繁琐,于是就需要Vuex这样一个可以对这一部分数据进行统一管理的东西,也是响应式

什么情况需要使用Vuex管理状态在多个组件间共享?

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

大型项目中组件很多,多个组件中共用的数据
例如:用户的登录状态、用户名称、头像、地理位置信息等
例如:商品的收藏、购物车中的物品。
例如:传递组件之间传递层次太多、不相关组件、公用组件

Vuex有点类似cookie和session,session是用于服务器端共享,cookie是用于浏览器的,Vuex是用于前端组件间共享

1.3 Vuex的工作原理图

在这里插入图片描述

四个核心概念
Vuex 的四个核心概念分别是:

  • The state tree:Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。至此它便作为一个『唯一数据源(SSOT)』而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
  • Getters:用来从 store 获取 Vue 组件数据。
  • Mutation:事件处理器用来驱动状态的变化。
  • Actions:可以给组件使用的函数,以此用来驱动事件处理器 mutations

Vuex和简单的全局对象是不同的,当Vuex从store中读取状态值的时候,若状态发生了变化,那么相应的组件也会高效的更新。并且,改变store中状态的唯一途径就是提交commit mutations。这样便于我们跟踪每一次状态的变化。只要发生了状态的变化,一定伴随着mutation的提交。

2 使用Vuex

2.1 搭建Vuex环境

  1. 下载安装 Vuex npm i vuex@3
    npm i vuex 是安装最新版本的Vuex
    注意:
  • Vue2中,要用Vuex的3版本
  • Vue3中,要用Vuex的4版本
  1. 创建 src/store/index.js 该文件用于创建Vuex中最为核心的 store

文件目录
在这里插入图片描述
store/index.js

写法一:

import Vue from 'vue'
import Vuex from 'vuex'   //引入VuexVue.use(Vuex)    //应用Vuex//创建并暴露store
export default new Vuex.Store({//数据,相当于datastate: {},getters: {},      //里面定义方法,操作state方法mutations: {},    // 操作数据Stateactions: {},     //用于响应组件中的动作modules: {},    
})

写法二:

import Vue from 'vue'
import Vuex from 'vuex'   //引入VuexVue.use(Vuex)    //应用Vuexconst actions = {}     //用于响应组件中的动作const mutations = {}   // 操作数据Stateconst state = {}const getters= {}   //里面定义方法,操作state方法const modules1 = {}const modules2 = {}//创建并暴露store
export default new Vuex.Store({//数据,相当于datastate,getters,      mutations,    actions,    modules: {modules1,modules2}   
})
  1. src/main.js 中创建vm中传入store配置项
    在这里插入图片描述

2.2 Vuex基本使用

Vuex的基本使用
Vuex中一共有五个状态 State、Getter、Mutation、Action、Module

2.2.1 State

提供唯一的公共数据源,所有共享的数据统一放到store的state进行储存,相似与data
在vuex中state中定义数据,可以在任何组件中进行调用

import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({//数据,相当于datastate: {name:"张三",age:12,sex: '男',count:0},
})

读取
方法一:在标签中直接使用

<p>{{ $store.state.name }}</p>
<p>{{ $store.state.age}}</p>

方法二:

this.$store.state.全局数据名称

方法三:
从vuex中按需导入mapstate函数

// 1. 从 vuex 中按需导入 mapState 函数
import { mapState } from "vuex";

通过刚才导入的 mapState 函数,将当前组件需要的全局数据,映射为当前组件的 computed 计算属性

// 2. 将全局数据,映射为当前组件的计算属性 
computed: { // 对象写法...mapState({name:'name', age:'age', sex:'sex'}) // 数组写法...mapState(['name', 'age', 'sex']) 
}

在这里插入图片描述
修改Vuex中的数据

$store.dispatch('action中的方法名',数据)
//或是
$store.commit('mutations中的方法名',数据)

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

2.2.2 Getters

Getters 用于对 Store 中的数据进行加工处理形成新的数据。

①Getters 可以对 Store 中已有的数据加工处理之后形成新的数据,类似 Vue 的计算属性。
②Store 中数据发生变化,Getters 的数据也会跟着变化。

具体操作类似于前几种
在Vuex中定义:

// 定义 Getters
export default new Vuex.Store({state: {count: 0},getters: {showNum: state => {return '当前最新的数量是【'+ state.count * 10 +'】'}}
})

在组件中使用:

方法一:在标签中直接使用

<p>{{ $store.getter.name }}</p>
<p>{{ $store.state.age}}</p>

方法二:

this.$store.getters.名称

方法二:
从vuex中按需导入mapGetters 函数

import { mapGetters } from 'vuex'

通过刚才导入的 mapGetters 函数,用于帮助映射 getters中的数据为当前组件的 computed 计算属性

computed: {//对象写法...mapGetters({showNum:'showNum'})//数组写法...mapGetters(['showNum'])
}

2.2.3 Mutations

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

① 只能通过 mutations 变更 Store 数据,不可以直接操作 Store 中的数据。
② 通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化。

在Vuex中定义

export default new Vuex.Store({//数据,相当于datastate: {name:"张三",age:12,sex: '男',count:0},mutations: {addCount(state, num) {state.count += num},reduce(state){state.count--}}
})

在组件中使用:
方法一:使用commit触发Mutations操作

// 触发mutations 
methods: { btn() { // 触发 mutations 的第一种方式 this.$store.commit('addCount', 10)     //每次加十} btn2() { // 触发 mutations 的第一种方式 this.$store.commit('reduce') } 
}

方法二:使用辅助函数进行操作,具体方法同上
从vuex中按需导入mapMutations 函数

// 1. 从 vuex 中按需导入 mapMutations 函数
import { mapMutations } from 'vuex'

通过刚才导入的 mapMutations 函数,将需要的 mutations 函数,映射为当前组件的 methods 方法

// 2. 将指定的 mutations 函数,映射为当前组件的 methods 函数
methods: {// 触发 mutations 的第二种方式 对象写法...mapMutations({addCount: 'addCount', reduce:'reduce'}),//或是// 触发 mutations 的第二种方式 数组写法...mapMutations(['addCount', 'reduce']),btn() { this.addCount(10)     //每次加十} btn2() { this.reduce() } 
}

2.2.4 Actions

Actions 用于处理异步任务。
如果通过异步操作变更数据,必须通过 Actions,而不能使用 Mutation,但是在 Actions 中还是要通过触发Mutation 的方式间接变更数据。

在Vuex中定义:

讲上面的操作改为异步操作

// 定义 Actions
export default new Vuex.Store({ // ...省略其他代码 mutations: { //第一个参数是state,第二参数是传的参数addCount(state, num) { //state中的数据的改变会触发页面上对应数据的改变state.count += num},reduce(state){state.count--}}, // 异步操作actions: { asynReduce(context) { setTimeout(() => { context.commit('reduce') }, 1000) },//触发 actions 异步任务时携带参数,第一个参数是上下文对象,第二参数是传的参数asynAdd(context, num) { setTimeout(() => { //会找到mutation对应的方法context.commit('addCount', num) }, 1000) }  } 
})

在组件中使用:
方法一:直接使用 dispatch触发Action函数

methods: {btn() { // 触发 actions 的第一种方式this.$store.dispatch("asynAdd", 10)} btn2() { // 触发 actions 的第一种方式this.$store.dispatch("asynReduce")} 
}

方法二:使用辅助函数
从vuex中按需导入mapActions 函数

// 1. 从 vuex 中按需导入 mapActions 函数 
import { mapActions } from 'vuex'

通过刚才导入的 mapActions 函数,将需要的 actions 函数,映射为当前组件的 methods 方法

// 2. 将指定的 actions 函数,映射为当前组件的 methods 函数 
methods: { //对象写法...mapActions({asynAdd:'asynAdd', asynReduce:'asynReduce'}),//或是//数组写法...mapActions(['asynAdd', 'asynReduce']),btn() { this.asynAdd(10)     //每次加十} btn2() { this.asynReduce() } 
}

2.2.5 Modules 模块化+命名空间

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

  2. 场景:当遇见大型项目时,数据量大,store就会显得很臃肿
    为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

  3. 基本写法
    写法一:

const countAbout = {namespaced: true,state: {sum: 0,name: 'zhangsan',sex: 'man',},mutations: {...},actions: {...},getters: {bisSum(state){ return state.sum * 10}
}const personAbout= {namespaced: true,state: {personList: [{id: '0001',name: 'Lisi'}]},mutations: {...},actions: {...},getters: { ... }
}const store = new Vuex.Store({modules: {countAbout,personAbout}
})

写法二:

const store = new Vuex.Store({modules: {countAbout:{namespaced: true,state: { ... },mutations: {...},actions: {...},getters: { ... }},personAbout: {namespaced: true,state: { ... },mutations: {...},actions: {...},getters: { ... }}}
})

默认情况下,模块内部的 action 和 mutation 仍然是注册在全局命名空间的——这样使得多个模块能够对同一个 action 或 mutation 作出响应。

如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。

  1. 开启命名空间后,组件中读取state数据
//方法一:自己读取
this.$store.state.countAbout.sum
//方法二:借助mapState读取
...mapState('countAbout', ['sum', 'name', 'sex'])
  1. 开启命名空间后,组件中读取getters数据
//方法一:自己读取
this.$store.getters['personAbout/firstPersonName']
//方法二:借助mapGetters读取
...mapGetters('countAbout', ['bisSum'])
  1. 开启命名空间后,组件中调用commit
//方法一:自己commit
this.$store.commit('personAbout/addPerson', person)
//方法二:借助mapMutations读取
...mapMutations('countAbout',{increment: 'add', decrement: 'reduce'})
  1. 开启命名空间后,组件中调用dispatch
//方法一:自己commit
this.$store.dispatch('personAbout/addPersonWang', person)
//方法二:借助mapMutations读取
...mapActions('countAbout',{incrementOdd:'asyncAddOdd', incrementWait:'asyncAddWait'})

3 求和案例

3.1 使用纯vue编写

在这里插入图片描述

App.vue

<template><div class="container"><Count/></div>
</template><script>
import Countfrom './components/Count'
export default {name: 'App',components: {Count}
}
</script>
<style></style>

Count.vue

<template><div class="hello"><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(() => {this.sum += this.n}, 500);}}
}
</script>
<style scoped></style>

3.2 使用Vuex编写

3.2.1 原始写法

src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'   //引入VuexVue.use(Vuex)    //应用Vuex//创建并暴露store
export default new Vuex.Store({//数据,相当于datastate: {sum: 0,name: 'zhangsan',sex: 'man'},getters: {},      //里面定义方法,操作state方法mutations: {add(state, num) {state.sum += num},reduce(state){state.sum--}},    // 操作异步操作mutationactions: {asyncAddWait(context, num){setTimeout(()=>{context.commit('add', num)},500)},asyncAddOdd(context, num){if(context.state.sum % 2){context.commit('add', num)}}},     //用于响应组件中的动作modules: {},    
})

Count.vue

<template><div class="hello"><h1>当前求和为:{{$store.state.sum}}</h1><h3>当前求和放大10倍:{{$store.getters.bigSum}}</h3><h3>姓名:{{ $store.statename }},性别: {{ $store.statesex }}</h3><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}},methods: {//使用mutaionincrement() {this.$store.commit('add', this.n)},decrement() { this.$store.commit('reduce')},//使用Actions异步incrementOdd() {this.$store.dispatch('asyncAddOdd', this.n)},incrementWait() {this.$store.dispatch('asyncAddWait', this.n)}}
}
</script>
<style scoped></style>

3.2.2 用mapXXX优化后

Count.vue

<template><div class="hello"><h1>当前求和为:{{ sum }}</h1><h3>当前求和放大10倍:{{bigSum}}</h3><h3>姓名:{{ name }},性别: {{ sex }}</h3><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="increment(n)">+</button><button @click="decrement(n)">-</button><button @click="incrementOdd(n)">当前求和为奇数再加</button><button @click="incrementWait(n)">等一等再加</button></div>
</template><script>
import {mapState,mapGetters,mapMutations, mapActions} from 'vuex'
export default {name: 'Count',data() {return {n: 1}},computed: {//借助mapSate和mapGetters生成计算属性...mapState(['sum','name','sex']),...mapGetters(['bigSum'])},methods: {...mapMutations({increment: 'add', decrement: 'reduce'}),...mapActions({incrementOdd:'asyncAddOdd', incrementWait:'asyncAddWait'})//使用mutaion//increment() {this.$store.commit('add', this.n)},//decrement() { this.$store.commit('reduce')},//使用Actions异步//incrementOdd() {this.$store.dispatch('asyncAddOdd', this.n)},//incrementWait() {this.$store.dispatch('asyncAddWait', this.n)}}
}
</script>
<style scoped></style>

3.2.2 多组件共享数据

在这里插入图片描述
src/App.vue

<template><div class="container"><Count/><Person/></div>
</template><script>
import Count from './components/Count'
import Person from './components/Person'
export default {name: 'App',components: {Count,Person}
}
</script>
<style></style>

src/components/Count.vue

<template><div class="hello"><h1>当前求和为:{{ sum }}</h1><h3>当前求和放大10倍:{{bigSum}}</h3><h3>姓名:{{ name }},性别: {{ sex }}</h3><h3 style="color:red">Person组件的总人数是: {{ personList.length }}</h3><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="increment(n)">+</button><button @click="decrement(n)">-</button><button @click="incrementOdd(n)">当前求和为奇数再加</button><button @click="incrementWait(n)">等一等再加</button></div>
</template><script>
import {mapState,mapGetters,mapMutations, mapActions} from 'vuex'
export default {name: 'Count',data() {return {n: 1}},computed: {//借助mapSate和mapGetters生成计算属性...mapState(['sum','name','sex','personList']),...mapGetters(['bigSum'])},methods: {...mapMutations({increment: 'add', decrement: 'reduce'}),...mapActions({incrementOdd:'asyncAddOdd', incrementWait:'asyncAddWait'})}
}
</script>
<style scoped></style>

src/components/Person.vue

<template><div><hr><h1>人员列表</h1><h3 style="color:red">Count组件求和为: {{ sum }}</h3><input type="text" placeholder="请输入" v-model="name"><button @click="add">添加</button><br><br><ul><li v-for="p in personList" :key="p.id">{{p.name}}</li></ul></div>
</template><script>
import {mapState} from 'vuex'
import {nanoid} from 'nanoid'
export default {name: 'Person',components: {},props: {},data() {return {name: ''};},computed:{...mapState(['personList', 'sum'])},methods: {add() {if(this.name === '') return const personObj = {id: nanoid(), name: this.name}this.$store.commit('addPerson', personObj)this.name = ''}}
};
</script>
<style scoped></style>

src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'   //引入VuexVue.use(Vuex)    //应用Vuex//创建并暴露store
export default new Vuex.Store({//数据,相当于datastate: {sum: 0,name: 'zhangsan',sex: 'man',personList: [{id: '0001',name: 'Lisi'}]},//里面定义方法,操作state方法getters: {bigSum: state=>{return state.sum * 10}},    // 操作异步操作mutation  mutations: {add(state, num) {state.sum += num},reduce(state){state.sum--},addPerson(state, value) {state.personList.unshift(value)}},   //用于响应组件中的动作 actions: {asyncAddWait(context, num){setTimeout(()=>{context.commit('add', num)},500)},asyncAddOdd(context, num){if(context.state.sum % 2){context.commit('add', num)}}},     
})

3.2.3 模块化优化后

在这里插入图片描述

src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'   //引入Vuex
import countOptions from './count'
import personOptions from './person'
import count from './count'
Vue.use(Vuex)    //应用Vuex//创建并暴露store
export default new Vuex.Store({modules: {countAbout: countOptions,personAbout: personOptions},    
})

src/store/count.js

export default {namespaced: true,state: {sum: 0,name: 'zhangsan',sex: 'man',},getters: {bigSum(state){return state.sum * 10}},mutations: {add(state, num) {state.sum += num},reduce(state){state.sum--},},actions: {asyncAddWait(context, num){setTimeout(()=>{context.commit('add', num)},500)},asyncAddOdd(context, num){if(context.state.sum % 2){context.commit('add', num)}}}
}

src/store/person.js

import axios from "axios"
import { nanoid } from 'nanoid'export default {namespaced: true,state: {personList: [{id: '0001',name: 'Lisi'}]},getters: {firstPersonName(state) {return state.personList[0].name}},mutations: {addPerson(state, value) {state.personList.unshift(value)}},actions: {addPersonWang(context, value) {if(value.name.indexOf('王') === 0){context.commit('addPerson', value)}else {alert('添加的人必须为王')}},addPersonServer(context) {axios.get('http://api.uixsj.cn/hitokoto/get?type=social').then(response => {context.commit('addPerson', {id: nanoid(), name:response.data})},error => {alert(error.message)})}}
}

Count和Person的呈现了两种不同的写法,一个是用mapXXX的写法,一个是直接使用this.$store的写法
src/components/Count.vue

<template><div class="hello"><h1>当前求和为:{{ sum }}</h1><h3>当前求和放大10倍:{{bigSum}}</h3><h3>姓名:{{ name }},性别: {{ sex }}</h3><h3 style="color:red">Person组件的总人数是: {{ personList.length }}</h3><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="increment(n)">+</button><button @click="decrement(n)">-</button><button @click="incrementOdd(n)">当前求和为奇数再加</button><button @click="incrementWait(n)">等一等再加</button></div>
</template><script>
import {mapState,mapGetters,mapMutations, mapActions} from 'vuex'
export default {name: 'Count',data() {return {n: 1}},computed: {//借助mapSate和mapGetters生成计算属性...mapState('countAbout',['sum','name','sex']),...mapState('personAbout', ['personList']),...mapGetters('countAbout',['bigSum'])},methods: {...mapMutations('countAbout',{increment: 'add', decrement: 'reduce'}),...mapActions('countAbout',{incrementOdd:'asyncAddOdd', incrementWait:'asyncAddWait'})}
}
</script>
<style scoped></style>

src/components/Person.vue

<template><div><hr><h1>人员列表</h1><h3 style="color:red">Count组件求和为: {{ sum }}</h3><h3>列表中第一个人的名字是: {{ firstPersonName }}</h3><input type="text" placeholder="请输入" v-model="name"><button @click="add">添加</button><button @click="addWang">添加一个姓王的人</button><button @click="addRandom">随机添加一个人</button><br><br><ul><li v-for="p in personList" :key="p.id">{{p.name}}</li></ul></div>
</template><script>
import {mapState, mapGetters,mapMutations,mapActions} from 'vuex'
import {nanoid} from 'nanoid'
export default {name: 'Person',components: {},props: {},data() {return {name: ''};},computed:{//直接读取的方法personList() { return this.$store.state.personAbout.personList },sum() { return this.$store.state.countAbout.sum },firstPersonName() { return this.$store.getters['personAbout/firstPersonName'] }},methods: {add() {if(this.name === '') return const personObj = {id: nanoid(), name: this.name}this.$store.commit('personAbout/addPerson', personObj)this.name = ''},addWang() {if(this.name === '') return const personObj = {id: nanoid(), name: this.name}this.$store.dispatch('personAbout/addPersonWang', personObj)this.name = ''},addRandom() {this.$store.dispatch('personAbout/addPersonServer')}}
};
</script>
<style scoped>
</style>

4 求和案例2

4.1 props传递值

helloword子组件使用Home组件声明的变量,可采用之前学习的组件传递值的方法

Home组件

<template><div class="home"><h2>这是在单页模板中应用</h2><h3>{{count}}</h3><button @click="count--">-</button><button @click="count++">+</button><!-- 传递count给子组件helloword---><HelloWorld :count="count" msg="Welcome to Your Vue.js App"/></div>
</template><script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {name: 'Home',components: {HelloWorld},data() {return {count: 0}}
}
</script>

helloword子组件

<template><div class="hello"><h1>{{ msg }}</h1><h3>在子组件hellword中应用Home中的Data</h3><h3>{{count}}</h3></div>
</template><script>
export default {name: 'HelloWorld',props: {count: Number}
}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
……
</style>

效果在这里插入图片描述
若About组件想要使用Home组件的count,通过组件传递的方式也可实现,就是有点麻烦,需要传递给中介App组件,App组件再传递给About组件。

4.2 Vuex的state传递

因此,在这里可采用Vuex,其配置文件在/store/index.js

import { createStore } from 'vuex'export default createStore({state: {//任何地方都可使用这个状态管理num: 0},mutations: { },actions: {},modules: {}
})

Home.vue

<template><div class="home"><h2>使用全局的状态管理</h2><h3>{{$store.state.num}}</h3><button @click="$store.state.num--">-</button><button @click="$store.state.num++">+</button></div>
</template><script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'export default {name: 'Home',components: {HelloWorld},
}
</script>

About.vue

<template><div class="about"><h1>This is an about page</h1><h3>{{$store.state.num}}</h3></div>
</template>

效果
在这里插入图片描述
在这里插入图片描述

4.3 Matuations来修改状态

Vuex最好采用Matuations来修改状态,而不是通过组件的形式
index.js

import { createStore } from 'vuex'export default createStore({state: {//任何地方都可使用这个状态管理num: 0,mnum: 0},mutations: {//自动把state的参数传过来sub(state) {state.mnum--;},add(state) {state.mnum++;}},actions: { },modules: {}
})

Home.vue

<template><div class="home"><h2>这是在单页模板中应用</h2><h3>{{count}}</h3><button @click="count--">-</button><button @click="count++">+</button><HelloWorld :count="count" msg="Welcome to Your Vue.js App"/><hr><h2>使用全局的状态管理</h2><h3>{{$store.state.num}}</h3><button @click="$store.state.num--">-</button><button @click="$store.state.num++">+</button><hr><h2>使用Mutations来修改状态</h2><h3>MNum:{{$store.state.mnum}}</h3><button @click="sub1()">-</button><button @click="add1()">+</button></div>
</template><script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'export default {name: 'Home',components: {HelloWorld},data() {return {count: 0}},methods: {add1() {this.$store.commit('add')},sub1() {this.$store.commit('sub')},}
}
</script>

About.vue

<template><div class="about"><h1>This is an about page</h1><h3>Num:{{$store.state.num}}</h3><h3>MNum:{{$store.state.mnum}}</h3></div>
</template>

效果
在这里插入图片描述
在这里插入图片描述

4.4 Mutations带参数传递修改状态

index.js

import { createStore } from 'vuex'export default createStore({state: {//任何地方都可使用这个状态管理num: 0,mnum: 0},mutations: {//自动把state的参数传过来sub(state) {state.mnum--;},add(state) {state.mnum++;},//接收一个参数sub2(state,count) {console.log(count);state.mnum-=count;},add2(state,count) {console.log(count);state.mnum+=count;},//接收多个参数sub3(state,payload) {console.log(payload);state.mnum-=(payload.count+payload.num);},add3(state,payload) {console.log(payload);state.mnum+=(payload.count+payload.num);}},actions: {},modules: {}
})

Home.vue

<template><div class="home"><hr><h2>使用Mutations来修改状态</h2><h3>MNum:{{$store.state.mnum}}</h3><button @click="sub1()">-</button><button @click="add1()">+</button><hr><h2>使用Mutations来修改状态带一个参数</h2><h3>MNum:{{$store.state.mnum}}</h3><button @click="sub2()">-</button><button @click="add2()">+</button><hr><h2>使用Mutations来修改状态带多个参数</h2><h3>MNum:{{$store.state.mnum}}</h3><button @click="sub3()">-</button><button @click="add3()">+</button></div>
</template><script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'export default {name: 'Home',components: {HelloWorld},data() {return {count: 0}},methods: {add1() {this.$store.commit('add')},sub1() {this.$store.commit('sub')},add2() {let count = 2;this.$store.commit('add2',count)},sub2() {let count = 2;this.$store.commit('sub2',count)},add3() {let payload = {count:2, num:1}this.$store.commit('add3',payload)},sub3() {let payload = {count:2, num:1}this.$store.commit('sub3',payload)//等价于//this.$store.commit({type:'sub3', payload})}}
}
</script>

效果
在这里插入图片描述

5 多组件共享数据案例


http://www.ppmy.cn/news/432667.html

相关文章

推荐几款适用的项目管理工具,助力您的项目更高效运作

随着企业规模的扩大和业务范围的增加&#xff0c;中小型企业近年来越来越重视项目管理。Zoho Projects 是一款适用于中小型企业的项目管理工具&#xff0c;可以帮助中小型企业更好地进行项目管理&#xff0c;提高工作效率和协作效果。 一、强大的项目管理能力 Zoho Projects提供…

DJ8-4 shell 语句的分类、shell 的结构性语句

目录 8.7 shell 编程 8.7.1 shell 编程的基本过程 8.7.2 实例 8.7.3 shell 程序和语句 8.8 说明性语句和功能性语句 8.8.1 说明性语句&#xff08;注释行&#xff09; 8.8.2 常用的功能性语句 8.9 结构性语句 8.9.1 条件语句 if 8.9.2 测试语句 test 8.9.…

投资框架2018

投资框架2018 2018-02-09 李国飞 李国飞哲学与投资笔记 说明&#xff1a;本文2018年2月3日演讲于高礼价值投资研习班深圳第五次课程&#xff0c;算是我多年思考投资的一个总结。这个投资框架是探讨投资决策、公司基本面和股价这三者的内在变化以及相互间的联系和影响&#xf…

MATLAB小波图像融合处理

目 录 摘 要 1 Abstract 1 1、 绪论 2 1.1 课题开发背景 2 1.1.1 图像融合的定义 2 1.1.2 手动配准与图象融合 2 1.1.3 图象融合研究的发展现状和研究热点 3 1.2 课题设计要求 4 2、MATLAB程序设计 5 2.1 MATLAB软件简介 5 2.2 MATLAB软件窗口环境 7 2.3 M语言编程 8 3、图像融…

“超限”之下,OLED迎来最好的反击

文丨佘凯文 来源丨智能相对论 自OLED进入电视舞台以来&#xff0c;关于“OLED已输”&#xff0c;“OLED将死”或是“OLED最多还有5年寿命”等等言论大量充斥各个媒介&#xff0c;与之相反的则是QLED概念的大行其道“广受追捧”。 一场“OQ”之间的争夺在电视机市场持续进行着…

(附源码)spring boot社区居民健康档案管理系统 毕业设计 220940

springboot 社区居民健康档案管理系统 摘 要 目前随着人们对健康认识的不断深入&#xff0c;健康观念也正在由有病治病向无病预防的方向改变&#xff0c;人们开始更加注重生活的质量&#xff0c;追求更健康&#xff0c;更长寿。因此&#xff0c;开发一个面向个社区居民&#xf…

(附源码)Springboot社区居民健康档案管理系统 毕业设计 220940

springboot 社区居民健康档案管理系统 摘 要 目前随着人们对健康认识的不断深入&#xff0c;健康观念也正在由有病治病向无病预防的方向改变&#xff0c;人们开始更加注重生活的质量&#xff0c;追求更健康&#xff0c;更长寿。因此&#xff0c;开发一个面向个社区居民&#xf…

spring boot社区居民健康档案管理系统毕业设计源码220940

springboot 社区居民健康档案管理系统 摘 要 目前随着人们对健康认识的不断深入&#xff0c;健康观念也正在由有病治病向无病预防的方向改变&#xff0c;人们开始更加注重生活的质量&#xff0c;追求更健康&#xff0c;更长寿。因此&#xff0c;开发一个面向个社区居民&#xf…