Vue2向Vue3过度Vuex核心概念module模块 深碍√TFBOYSˉ_ 2024-03-24 21:51 40阅读 0赞 #### 目录 #### * * 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 ### ![在这里插入图片描述][6c5afcf1c4d546dbbb3d078d3592efcd.png] #### 1.目标 #### 掌握核心概念 module 模块的创建 #### 2.问题 #### 由于使用**单一状态树**,应用的所有状态**会集中到一个比较大的对象**。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。 这句话的意思是,如果把所有的状态都放在state中,当项目变得越来越大的时候,Vuex会变得越来越难以维护 由此,又有了Vuex的模块化 ![在这里插入图片描述][d42d632e954b46d7aa951143e1c6ea28.png] #### 3.模块定义 - 准备 state #### 定义两个模块 **user** 和 **setting** 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 中,属性名就是模块名 ![在这里插入图片描述][086bfb1dcc5546cd859356950a6b80f7.png] #### 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.代码实现 #### 需求: ![在这里插入图片描述][b894aea4a5f24110a9da590ac3c832b6.png] `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-准备代码》 ![在这里插入图片描述][62cfc037e0a94eb2bb54ad942dde641b.png] 需求: 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, 映射渲染 ![在这里插入图片描述][8cf3a3b0168b462e8fbc324f8b2e839b.png] 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 综合案例-修改数量 ### ![在这里插入图片描述][153b9faa191b48ccb9c2b30678adcfa9.png] 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> [6c5afcf1c4d546dbbb3d078d3592efcd.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/13/f6c8db6b76ff4c2f8cf35bc1baf29121.png [d42d632e954b46d7aa951143e1c6ea28.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/13/02b17af119c1441ba12143f35275023d.png [086bfb1dcc5546cd859356950a6b80f7.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/13/369225cebc80445fa0302a4ffe8c2862.png [b894aea4a5f24110a9da590ac3c832b6.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/13/5c8ae22afd3740cc8775802889fefa5b.png [62cfc037e0a94eb2bb54ad942dde641b.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/13/efdeea6f38d14e2e95e4d44e632aa9c5.png [8cf3a3b0168b462e8fbc324f8b2e839b.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/13/d070e8392e6e40de963c10fbd652d59e.png [153b9faa191b48ccb9c2b30678adcfa9.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/13/63abbfb93bcb407dae7fe2b54bd0081b.png
相关 Vue2向Vue3过度Vuex核心概念getters 目录 1 核心概念 - getters 1.定义getters 2.使用getters 朱雀/ 2024年03月24日 21:52/ 0 赞/ 55 阅读
相关 Vue2向Vue3过度Vuex核心概念actions 目录 1 核心概念 - actions 1.定义actions 2.组件中通过dispatch调用 2 妖狐艹你老母/ 2024年03月24日 21:52/ 0 赞/ 46 阅读
相关 Vue2向Vue3过度Vuex核心概念mutations 目录 1 核心概念-mutations 1.定义mutations 2.格式说明 3.组件中提 绝地灬酷狼/ 2024年03月24日 21:51/ 0 赞/ 46 阅读
相关 Vue2向Vue3过度Vuex核心概念module模块 目录 1 核心概念 - module 1.目标 2.问题 3.模块定义 - 准备 state 深碍√TFBOYSˉ_/ 2024年03月24日 21:51/ 0 赞/ 41 阅读
相关 Vue2向Vue3过度Vuex核心概念state状态 目录 1 核心概念 - state 状态 1.目标 2.提供数据 3.访问Vuex中的数据 阳光穿透心脏的1/2处/ 2024年03月24日 21:51/ 0 赞/ 40 阅读
相关 Vue2向Vue3过度核心技术综合案例 目录 1 面经基础版-案例效果分析 1.面经效果演示 2.功能分析 3.实现思路分析:配置路由 曾经终败给现在/ 2024年03月24日 21:50/ 0 赞/ 55 阅读
相关 Vue2向Vue3过度核心技术插槽 目录 1 插槽-默认插槽 1.作用 2.需求 3.问题 4.插槽的基本语 Love The Way You Lie/ 2024年03月24日 21:48/ 0 赞/ 48 阅读
相关 Vue2向Vue3过度核心技术组件通信 目录 1 组件基础知识scoped解决样式冲突 1.1 默认情况: 1.2 代码演示 1.3 浅浅的花香味﹌/ 2024年03月24日 21:37/ 0 赞/ 56 阅读
相关 Vue2向Vue3过度核心技术生命周期 目录 1 Vue生命周期 2 Vue生命周期钩子 3 生命周期钩子小案例 1.1 在created中发送数据 小灰灰/ 2024年03月24日 21:35/ 0 赞/ 30 阅读
还没有评论,来说两句吧...