Vue2向Vue3过度Vuex核心概念module模块

目录

    • 1 核心概念 - module
      • 1.目标
      • 2.问题
      • 3.模块定义 - 准备 state
    • 2 获取模块内的state数据
      • 1.目标:
      • 2.使用模块中的数据
      • 3.代码示例
    • 3 获取模块内的getters数据
      • 1.目标:
      • 2.语法:
      • 3.代码演示
    • 4 获取模块内的mutations方法
      • 1.目标:
      • 2.注意:
      • 3.调用方式:
      • 4.代码实现
    • 5 获取模块内的actions方法
      • 1.目标:
      • 2.注意:
      • 3.调用语法:
      • 4.代码实现
    • 6 Vuex模块化的使用小结
      • 1.直接使用
      • 2.借助辅助方法使用
    • 7 综合案例 - 创建项目
    • 8 综合案例-构建vuex-cart模块
    • 9 综合案例-准备后端接口服务环境
    • 10 综合案例-请求动态渲染数据
      • 1.目标
    • 11 综合案例-修改数量
    • 12 综合案例-底部总价展示


1 核心概念 - module

在这里插入图片描述

1.目标

掌握核心概念 module 模块的创建

2.问题

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

这句话的意思是,如果把所有的状态都放在state中,当项目变得越来越大的时候,Vuex会变得越来越难以维护

由此,又有了Vuex的模块化

在这里插入图片描述

3.模块定义 - 准备 state

定义两个模块 usersetting

user中管理用户的信息状态 userInfo modules/user.js

const state = {
  userInfo: {
    name: 'zs',
    age: 18
  }
}

const mutations = {}

const actions = {}

const getters = {}

export default {
  state,
  mutations,
  actions,
  getters
}

setting中管理项目应用的 主题色 theme,描述 desc, modules/setting.js

const state = {
  theme: 'dark'
  desc: '描述真呀真不错'
}

const mutations = {}

const actions = {}

const getters = {}

export default {
  state,
  mutations,
  actions,
  getters
}

store/index.js文件中的modules配置项中,注册这两个模块

import user from './modules/user'
import setting from './modules/setting'

const store = new Vuex.Store({
    modules:{
        user,
        setting
    }
})

使用模块中的数据, 可以直接通过模块名访问 $store.state.模块名.xxx => $store.state.setting.desc

也可以通过 mapState 映射

2 获取模块内的state数据

1.目标:

掌握模块中 state 的访问语法

尽管已经分模块了,但其实子模块的状态,还是会挂到根级别的 state 中,属性名就是模块名

在这里插入图片描述

2.使用模块中的数据

  1. 直接通过模块名访问 $store.state.模块名.xxx
  2. 通过 mapState 映射:
    1. 默认根级别的映射 mapState([ ‘xxx’ ])
    2. 子模块的映射 :mapState(‘模块名’, [‘xxx’]) - 需要开启命名空间 namespaced:true

modules/user.js

const state = {
  userInfo: {
    name: 'zs',
    age: 18
  },
  myMsg: '我的数据'
}

const mutations = {
  updateMsg (state, msg) {
    state.myMsg = msg
  }
}

const actions = {}

const getters = {}

export default {
  namespaced: true,
  state,
  mutations,
  actions,
  getters
}

3.代码示例

$store直接访问

$store.state.user.userInfo.name

mapState辅助函数访问

...mapState('user', ['userInfo']),
...mapState('setting', ['theme', 'desc']),

3 获取模块内的getters数据

1.目标:

掌握模块中 getters 的访问语

2.语法:

使用模块中 getters 中的数据:

  1. 直接通过模块名访问 $store.getters['模块名/xxx ']
  2. 通过 mapGetters 映射
    1. 默认根级别的映射 mapGetters([ 'xxx' ])
    2. 子模块的映射 mapGetters('模块名', ['xxx']) - 需要开启命名空间

3.代码演示

modules/user.js

const getters = {
  // 分模块后,state指代子模块的state
  UpperCaseName (state) {
    return state.userInfo.name.toUpperCase()
  }
}

Son1.vue 直接访问getters

<!-- 测试访问模块中的getters - 原生 -->
<div>{{ $store.getters['user/UpperCaseName'] }}</div>

Son2.vue 通过命名空间访问

computed:{
  ...mapGetters('user', ['UpperCaseName'])
}

4 获取模块内的mutations方法

1.目标:

掌握模块中 mutation 的调用语法

2.注意:

默认模块中的 mutation 和 actions 会被挂载到全局,需要开启命名空间,才会挂载到子模块。

3.调用方式:

  1. 直接通过 store 调用 $store.commit('模块名/xxx ', 额外参数)
  2. 通过 mapMutations 映射
    1. 默认根级别的映射 mapMutations([ ‘xxx’ ])
    2. 子模块的映射 mapMutations(‘模块名’, [‘xxx’]) - 需要开启命名空间

4.代码实现

modules/user.js

const mutations = {
  setUser (state, newUserInfo) {
    state.userInfo = newUserInfo
  }
}

modules/setting.js

const mutations = {
  setTheme (state, newTheme) {
    state.theme = newTheme
  }
}

Son1.vue

<button @click="updateUser">更新个人信息</button> 
<button @click="updateTheme">更新主题色</button>


export default {
  methods: {
    updateUser () {
      // $store.commit('模块名/mutation名', 额外传参)
      this.$store.commit('user/setUser', {
        name: 'xiaowang',
        age: 25
      })
    }, 
    updateTheme () {
      this.$store.commit('setting/setTheme', 'pink')
    }
  }
}

Son2.vue

<button @click="setUser({ name: 'xiaoli', age: 80 })">更新个人信息</button>
<button @click="setTheme('skyblue')">更新主题</button>

methods:{
// 分模块的映射
...mapMutations('setting', ['setTheme']),
...mapMutations('user', ['setUser']),
}

5 获取模块内的actions方法

1.目标:

掌握模块中 action 的调用语法 (同理 - 直接类比 mutation 即可)

2.注意:

默认模块中的 mutation 和 actions 会被挂载到全局,需要开启命名空间,才会挂载到子模块。

3.调用语法:

  1. 直接通过 store 调用 $store.dispatch('模块名/xxx ', 额外参数)
  2. 通过 mapActions 映射
    1. 默认根级别的映射 mapActions([ ‘xxx’ ])
    2. 子模块的映射 mapActions(‘模块名’, [‘xxx’]) - 需要开启命名空间

4.代码实现

需求:

在这里插入图片描述

modules/user.js

const actions = {
  setUserSecond (context, newUserInfo) {
    // 将异步在action中进行封装
    setTimeout(() => {
      // 调用mutation   context上下文,默认提交的就是自己模块的action和mutation
      context.commit('setUser', newUserInfo)
    }, 1000)
  }
}

Son1.vue 直接通过store调用

<button @click="updateUser2">一秒后更新信息</button>

methods:{
    updateUser2 () {
      // 调用action dispatch
      this.$store.dispatch('user/setUserSecond', {
        name: 'xiaohong',
        age: 28
      })
    },
}

Son2.vue mapActions映射

<button @click="setUserSecond({ name: 'xiaoli', age: 80 })">一秒后更新信息</button>

methods:{
  ...mapActions('user', ['setUserSecond'])
}

6 Vuex模块化的使用小结

1.直接使用

  1. state --> $store.state.模块名.数据项名
  2. getters --> $store.getters[‘模块名/属性名’]
  3. mutations --> $store.commit(‘模块名/方法名’, 其他参数)
  4. actions --> $store.dispatch(‘模块名/方法名’, 其他参数)

2.借助辅助方法使用

1.import { mapXxxx, mapXxx } from ‘vuex’

computed、methods: {

​ // …mapState、…mapGetters放computed中;

​ // …mapMutations、…mapActions放methods中;

​ …mapXxxx(‘模块名’, [‘数据项|方法’]),

​ …mapXxxx(‘模块名’, { 新的名字: 原来的名字 }),

}

2.组件中直接使用 属性 {{ age }} 或 方法 @click="updateAge(2)"

7 综合案例 - 创建项目

  1. 脚手架新建项目 (注意:勾选vuex)

    版本说明:

    vue2 vue-router3 vuex3

    vue3 vue-router4 vuex4/pinia

vue create vue-cart-demo
  1. 将原本src内容清空,替换成教学资料的《vuex-cart-准备代码》

在这里插入图片描述

需求:

  1. 发请求动态渲染购物车,数据存vuex (存cart模块, 将来还会有user模块,article模块…)
  2. 数字框可以修改数据
  3. 动态计算总价和总数量

8 综合案例-构建vuex-cart模块

  1. 新建 store/modules/cart.js
export default {
  namespaced: true,
  state () {
    return {
      list: []
    }
  },
}
  1. 挂载到 vuex 仓库上 store/cart.js
import Vuex from 'vuex'
import Vue from 'vue'

import cart from './modules/cart'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    cart
  }
})

export default store

9 综合案例-准备后端接口服务环境

  1. 安装全局工具 json-server (全局工具仅需要安装一次)
yarn global add json-server 或 npm i json-server  -g
  1. 代码根目录新建一个 db 目录
  2. 将资料 index.json 移入 db 目录
  3. 进入 db 目录,执行命令,启动后端接口服务 (使用–watch 参数 可以实时监听 json 文件的修改)
json-server  --watch  index.json

10 综合案例-请求动态渲染数据

1.目标

请求获取数据存入 vuex, 映射渲染

在这里插入图片描述

  1. 安装 axios
yarn add axios
  1. 准备actions 和 mutations
import axios from 'axios'

export default {
  namespaced: true,
  state () {
    return {
      list: []
    }
  },
  mutations: {
    updateList (state, payload) {
      state.list = payload
    }
  },
  actions: {
    async getList (ctx) {
      const res = await axios.get('http://localhost:3000/cart')
      ctx.commit('updateList', res.data)
    }
  }
}
  1. App.vue页面中调用 action, 获取数据
import { mapState } from 'vuex'

export default {
  name: 'App',
  components: {
    CartHeader,
    CartFooter,
    CartItem
  },
  created () {
    this.$store.dispatch('cart/getList')
  },
  computed: {
    ...mapState('cart', ['list'])
  }
}
  1. 动态渲染
<!-- 商品 Item 项组件 -->
<cart-item v-for="item in list" :key="item.id" :item="item"></cart-item>

cart-item.vue

<template>
  <div class="goods-container">
    <!-- 左侧图片区域 -->
    <div class="left">
      <img :src="item.thumb" class="avatar" alt="">
    </div>
    <!-- 右侧商品区域 -->
    <div class="right">
      <!-- 标题 -->
      <div class="title">{{item.name}}</div>
      <div class="info">
        <!-- 单价 -->
        <span class="price">¥{{item.price}}</span>
        <div class="btns">
          <!-- 按钮区域 -->
          <button class="btn btn-light">-</button>
          <span class="count">{{item.count}}</span>
          <button class="btn btn-light">+</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'CartItem',
  props: {
    item: Object
  },
  methods: {

  }
}
</script>

11 综合案例-修改数量

在这里插入图片描述

  1. 注册点击事件
<!-- 按钮区域 -->
<button class="btn btn-light" @click="onBtnClick(-1)">-</button>
<span class="count">{{item.count}}</span>
<button class="btn btn-light" @click="onBtnClick(1)">+</button>
  1. 页面中dispatch action
onBtnClick (step) {
  const newCount = this.item.count + step
  if (newCount < 1) return

  // 发送修改数量请求
  this.$store.dispatch('cart/updateCount', {
    id: this.item.id,
    count: newCount
  })
}
  1. 提供action函数
async updateCount (ctx, payload) {
  await axios.patch('http://localhost:3000/cart/' + payload.id, {
    count: payload.count
  })
  ctx.commit('updateCount', payload)
}
  1. 提供mutation处理函数
mutations: {
  ...,
  updateCount (state, payload) {
    const goods = state.list.find((item) => item.id === payload.id)
    goods.count = payload.count
  }
},

12 综合案例-底部总价展示

  1. 提供getters
getters: {
  total(state) {
    return state.list.reduce((p, c) => p + c.count, 0);
  },
  totalPrice (state) {
    return state.list.reduce((p, c) => p + c.count * c.price, 0);
  },
},
  1. 动态渲染
<template>
  <div class="footer-container">
    <!-- 中间的合计 -->
    <div>
      <span>共 {{total}} 件商品,合计:</span>
      <span class="price">¥{{totalPrice}}</span>
    </div>
    <!-- 右侧结算按钮 -->
    <button class="btn btn-success btn-settle">结算</button>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
export default {
  name: 'CartFooter',
  computed: {
    ...mapGetters('cart', ['total', 'totalPrice'])
  }
}
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/92508.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker,nvidia-docker安装

卸载先前的docker Docker 的旧版本被称为 docker&#xff0c;docker.io 或 docker-engine 。如果已安装&#xff0c;请卸载它们&#xff1a; sudo apt-get remove docker docker-engine docker.io containerd runc使用 Docker 仓库进行安装 设置仓库 更新 apt 包索引 sudo…

【C++】特殊类的设计

特殊类的设计 前言正式开始设计一个类&#xff0c;不能被拷贝设计一个类&#xff0c;只能在堆上创建对象设计一个类&#xff0c;只能在栈上创建对象设计一个类&#xff0c;不能被继承设计一个类&#xff0c;只能创建一个对象(单例模式)饿汉模式懒汉模式总结 前言 点进来的同学…

三次握手四次挥手之全连接半连接队列

什么是全连接半连接 在 TCP 三次握手的时候&#xff0c;Linux 内核会维护两个队列&#xff0c;分别是&#xff1a; 半连接队列&#xff0c;也称 Listen 队列&#xff1b;全连接队列&#xff0c;也称 accept 队列&#xff1b; 工作原理 每一个socket执行listen时&#xff0c…

BIO到NIO、多路复用器, 从理论到实践, 结合实际案例对比各自效率与特点(下)

文章目录 多路复用器简介多路复用器的两个阶段Java中的多路复用器封装测试代码压测结果总结 本篇文章是BIO到NIO、多路复用器, 从理论到实践, 结合实际案例对比各自效率与特点(上)的下一篇, 如果没有看的小伙伴, 可以先看下, 不然可能会不连贯. 多路复用器简介 多路复用器是对…

【QT】重写QAbstractLIstModel,使用ListView来显示多列数据

qt提供了几个视图来进行信息的列表显示&#xff0c;QListView可以用来显示继承QStractListModel的字符串列表中的字符串&#xff0c;默认的模型里面只包含一列的内容&#xff1a; 这里以qml为例子&#xff0c;先新建一个qml的项目&#xff0c;示例代码如下&#xff1a; 先创建一…

【提升接口响应能力的最佳实践】常规操作篇

文章目录 1. 并行处理简要说明CompletableFuture是银弹吗&#xff1f;测试案例测试结论半异步&#xff0c;半同步总结 2. 最小化事务范围简要说明编程式事务模板 3. 缓存简要说明 4. 合理使用线程池简要说明使用场景线程池的创建参数的配置建议 线程池的监控线程池的资源隔离 5…

idea的debug断点的使用

添加断点&#xff08;目前不知道如何添加断点&#xff0c;就给AutoConfigurationImportSelector的每个方法都加上断点&#xff09;&#xff1a; 然后将StockApplication启动类以debug方式运行&#xff0c;然后程序就会停在119行 点击上边的step over让程序往下运行一行&#x…

HLS实现CORDIC算法计算正余弦并上板验证

硬件&#xff1a;ZYNQ7010 软件&#xff1a;MATLAB 2019b、Vivado 2017.4、HLS 2017.4、System Generator 2017.4 1、CORDIC算法计算正余弦 CORDIC算法详细分析网上有很多资料&#xff0c;它的原理是用一系列旋转去逼近目标角度&#xff0c;这一系列旋转的角度为 θ a r c t…

Git gui教程---第七篇 Git gui的使用 返回上一次提交

1&#xff0e; 查看历史&#xff0c;打开gitk程序 2&#xff0e; 选中需要返回的版本&#xff0c;右键&#xff0c;然后点击Rest master branch to here 3.出现弹窗 每个选项我们都试一下&#xff0c;从Hard开始 返回的选项 HardMixedSoft Hard 会丢失所有的修改【此处的…

【Jellyfin影音服务器】 本地部署公网远程影音库

文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及&#xff0c;各种各样的使用需求也被开发出来&…

dig批量域名逆向查询ip

dig批量域名逆向查询ip dig nocmd noall answer -f iplist.txtiplist.txt中内容 效果图&#xff1a; dig其他选项参数&#xff1a; dig www.baidu.com A # 查询A记录&#xff0c;如果域名后面不加任何参数&#xff0c;默认查询A记录 dig www.baidu.com MX # 查询MX记…

重新认识Android中的线程

线程的几种创建方式 new Thread&#xff1a;可复写Thread#run方法。也可以传递Runnable对象&#xff0c;更加灵活。缺点&#xff1a;缺乏统一管理&#xff0c;可能无限制新建线程&#xff0c;相互之间竞争&#xff0c;及可能占用过多系统的资源导致死机或oom。 new Thread(new…

LeetCode-406-根据身高重建队列

题目描述&#xff1a; 假设有打乱顺序的一群人站成一个队列&#xff0c;数组 people 表示队列中一些人的属性&#xff08;不一定按顺序&#xff09;。每个 people[i] [hi, ki] 表示第 i 个人的身高为 hi &#xff0c;前面 正好 有 ki 个身高大于或等于 hi 的人。 请你重新构造…

VB.NET调用VB6 Activex EXE实现PowerBasic和FreeBasic的标准DLL调用

VB6写的ActiveX EXE公共对象是外置进程&#xff0c;因此&#xff0c;尽管它是x86 32位的进程&#xff0c;但可以集成到 VB.NET的x64和x32程序中使用。 VS2022的VB.NET程序&#xff0c;调用ActiveX DLL对象我在上篇笔记中写了 VB.NET通过VB6 ActiveX DLL调用PowerBasic及FreeB…

Git向远程仓库与推送以及拉取远程仓库

理解分布式版本控制系统 1.中央服务器 我们⽬前所说的所有内容&#xff08;⼯作区&#xff0c;暂存区&#xff0c;版本库等等&#xff09;&#xff0c;都是在本地也就是在你的笔记本或者计算机上。⽽我们的 Git 其实是分布式版本控制系统&#xff01;什么意思呢? 那我们多人…

计算机网络(10) --- 高级IO

计算机网络&#xff08;9&#xff09; --- 数据链路层与MAC帧_哈里沃克的博客-CSDN博客数据链路层与MAC帧https://blog.csdn.net/m0_63488627/article/details/132178583?spm1001.2014.3001.5501 目录 1.IO介绍 1.IO本质 2.IO模型 2.非阻塞 3.IO多路转接 1.select 编写…

电阻器件的分类

电阻器的种类碳膜电阻膜式电阻器中的一种。气态碳氢化合物在高温和真空中分解&#xff0c;碳沉积在瓷棒或者瓷管上&#xff0c;形成一层结晶碳膜。改变碳膜厚度和用刻槽的方式变更碳膜的长度可以得到不同的阻值。碳膜电阻成本较低&#xff0c;电性能和稳定性较差&#xff0c;一…

Python自动化小技巧21——实现PDF转word功能(程序制作)

案例背景 为什么这个年代PDF转word&#xff0c;某wps居然还要收费.....很多软件都可以实现这个功能&#xff0c;但是效果都有好有坏&#xff0c;而且有的还付费&#xff0c;很麻烦。 那就用python实现这个功能吧&#xff0c;然后把代码打包为.exe的程序&#xff0c;这样随便在…

企业网络日志安全与 EventLog Analyzer

企业的网络日志安全是一项至关重要的任务。随着信息技术的迅猛发展&#xff0c;网络攻击和数据泄露的威胁也与日俱增。为了应对这些威胁&#xff0c;企业需要强大的工具来监控、分析和保护其网络日志。而ManageEngine的EventLog Analyzer正是这样一款卓越的解决方案。 网络日志…

Sentinel 控制台(集群流控管理)

规则配置 要通过 Sentinel 控制台配置集群流控规则&#xff0c;需要对控制台进行改造。我们提供了相应的接口进行适配。 从 Sentinel 1.4.0 开始&#xff0c;我们抽取出了接口用于向远程配置中心推送规则以及拉取规则&#xff1a; DynamicRuleProvider<T>: 拉取规则Dy…