学生管理系统-04VueX

news2024/11/17 22:19:33

一、本章目标

  • vuex的简介【重点】

  • 掌握vuex的基本使用

  • 掌握辅助函数来操作vuex

  • 掌握vuex的模块化【难点】

  • 掌握vuex的持久化

  • 完成Tabs选项卡的二次封装

    • vuex的使用

    • 封装组件

    • 组件内路由守卫

二、vuex的简介

1、回顾组件之间的通讯

父组件向子组件通讯:通过props实现

子组件向父组件通讯:通过自定义事件($emit)方式来实现

兄弟组件之间的通讯:事件总线($eventBus)、订阅与发布方式来实现

跨级组件的通讯:可以通过(provider和inject)方式来实现

2、什么是Vuex

官网地址:Vuex 是什么? | Vuex

概念:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式库,它采用集中式存储管理应用的所有组件的状态

3、使用vuex的好处

  • 集中管理共享数据

  • 高效实现组件之间数据共享

  • vuex中的数据都是响应式的,能够实施保持数据与页面的同步

4、vuex和localStorage的区别

  • vuex是存储在内存中,localStroage存储数据在浏览器本地存储的

  • vuex的数据是瞬时的,localStroage是持久的,是不容易丢失的

  • vuex的数据是响应式的,localStorage中的数据不是响应式的

  • vuex直接操作JS的对象无需转换,localStorage存储数据要转成JSON,取数据要将JSON转成JS对

  • vuex还能完成异步操作(网络请求的),localStorage仅仅只是一个保存数据和获取数据

  • vuex中数据按照业务进行模块化,localStorage管理数据没有模块化

  • 单页面应用的程序组件数据共享使用使用状态机(vuex),localStorage适合多页面数据的共享

5、vuex的安装和基本配置

  • 下载vuex的依赖包

npm i vuex@3.6.2
  • 在src目录下创建一个store文件夹

  • 在src/store/index.js在此处完成vuex状态机仓库的基本配置

import Vue from 'vue'
import Vuex from 'vuex'
//将vuex以插件的方式设置到Vue中
Vue.use(Vuex)
/*
  创建仓库
  new Vuex.Store(参数)
  参数是状态机配置对象,状态机由5大部件组成
  state:状态,
  mutataion:改变数据
  actions:异步操作的
  getters:相当于是状态机中的计算属性
  modules:模块化
*/
const store=new Vuex.Store({
    state:{
        num:10
    }
})
//导出store
export default store
  • 挂载store到vue中

import Vue from 'vue'
import App from './App.vue'
import store from '@/store'
Vue.config.productionTip = false
​
new Vue({
  render: h => h(App),
  store
}).$mount('#app')

三、vuex的基本使用和原理

1、Store核心概念

  • state:用来存储状态的

  • Mutatations:State的数据只能通过Mutations才能改变

  • Actions:用来完成异步操作,比如从后端获取数据

2、vuex的原理

Vuex的执行的流程

  • VueComponents(Vue组件)通过执行dispatch向store对象的Actions发送命令,要求完成异步任务

  • Actions执行异步任务,比如向Backend API(后端)发送请求,从后端获取到结果

  • Actions通过执行commit要求Mutations更改State状态机的数据,Mutatations就开始执行这个操作

  • Vue Componetents(Vue组件)直接从仓库中获取数据

注意点:

  • 如果不执行异步任务,组件可以直接操作Mutatation来完成仓库中数据的改变

3、vuex的基本操作

这里以计数器的方式来讲解这个案例

3.1、state
  • 首先先在store/index.js的state部分定义状态机状态数据

const store=new Vuex.Store({
    state:{
        num:10
    }
})
  • 在组件中获取这个状态数据

组件中如果要获取store中的state数据的语法

如果要在js代码部分获取

this.$store.state.数据名

如果要在template部分获取

{{$store.state.数据名}}
或者
<div v-bind:属性="$store.state.数据名"></div>
3.2、mutations

组件中操作状态机的数据

如果组件内要更改状态机的数据,如果是通过的话,直接通过Mutatations的方式去操作

  • 在store对象配置对象中添加mutations选项,并定义要操作的方法

const store=new Vuex.Store({
    state:{
        num:10
    },
    mutations:{
        INCREMENT(state,payload){
            state.num++
        }
    }
})

参数说明

1) 参数1:state对象

2) 参数2:载荷数据,此数据来源于组件或者actions

  • 组件中操作state的数据

this.$store.commit(方法名,传递的参数)
export default {
   methods:{
    increment(){
        this.$store.commit('INCREMENT')
    }
   }
}
  • 如果组件需要给仓库中传递数据,可以通过载荷传值

const store=new Vuex.Store({
    state:{
        num:10
    },
    mutations:{
        INCREMENT_N(state,payload){
            state.num+=payload
        }
    }
})
export default {
   methods:{
    incrementN(n){
        this.$store.commit('INCREMENT_N',3)
    }
   }
}
3.3、actions

组件中要调用store仓库中的actions的语法

this.$store.dispatch('actions的相关方法名',参数)

购物车案例

  • 组件

<template>
    <div>
      <h2>购物车列表</h2>
       {{$store.state.shopcartList}}
       <table>
            <thead>
                <tr>
                    <td>ID</td>
                    <td>名称</td>
                    <td>数量</td>
                    <td>价格</td>
                    <td>小计</td>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(item,index) in $store.state.shopcartList" :key="item._id">
                    <td>{{index+1}}</td>
                    <td>{{item.name}}</td>
                    <td>{{item.num}}</td>
                    <td>{{item.price}}</td>
                    <td>{{item.num*item.price}}</td>
                </tr>
            </tbody>
       </table>
    </div>
</template>

<script>
export default {
    methods:{
        getShopcartList(){
            //调用store仓库中的actions,让其执行异步操作
            this.$store.dispatch('getShopcartList_Async')
        }  
    },
    created(){
        this.getShopcartList()
    }
}
</script>

<style>

</style>
  • store

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store=new Vuex.Store({
    state:{
        shopcartList:[]
    },
    mutations:{
       getShopcartList_Sync(state,payload){
         console.log('------2、store中的mutations的getShopcartList_Sync--------------');
         console.log('payload',payload);
         state.shopcartList=payload
       }
    },
    //完成异步操作
    actions:{
       async getShopcartList_Async(context){
         console.log('------1、store中的actions的getShopcartListAsync--------------');
         let result=await Vue.prototype.$api.shopcart.getShopcartData()
         console.log(result.data);
         console.log('context',context);
         context.commit('getShopcartList_Sync',result.data)
     }

    }
})
//导出store
export default store
3.4、getters

getters选项中专门是依赖于state数据,产生新的数据,就相当于组件中计算属性

语法

const store=new Vuex.Store({
   getters:{
      getter方法名称(state){
          return 处理后的数据
      }
   }
})

在组件中调用的语法

this.$store.getters.getter方法名称

案例:使用getters完成总价计算

const store=new Vuex.Store({
    getters:{
     totalPrice:state=>state.shopcartList.filter(item=>item.checked).reduce((prev,cur)=>prev+cur.price*cur.num,0)
    }
})

组件中方法问

 总价:{{$store.getters.totalPrice}}

四、辅助函数

之前我们如果要在组件中访问状态机仓库中的数据,或者操作状态机仓库的数据,必须通过this.$store这个对象来完成,除了这种方式之外,vuex为我们提供了另外一种组件中访问或者操作store的方式,这种方式就是辅助函数

辅助函数最重要的思想是将状态机中的数据或者方法映射成组件内方法

vuex中提供了以下四种常用方法

  • mapState():这个方法就是将状态机仓库中的state数据映射成组件内数据

  • mapMutatations():将状态机仓库中mutations选项中方法映射组件的方法

  • mapActions():将状态机仓库中actions选项中的方法映射成组件的方法

  • mapGetters():将状态机仓库中getters选项中的方法映射成组件内的计算属性

1、mapActions的使用

  • 导入mapActoins

import {mapActions} from 'vuex'
  • 在methods选项中使用扩展运算符来映射仓库中的actions选项的方法到组件中

export default{
    methods:{
        ...mapActions(["仓库中actions选项中的对应的方法名"])
    }
}
  • 直接调用

export default{
    methods:{
        ...mapActions(["getShopcartList_Async"]),
        getShopcartList(){
            this.getShopcartList_Async()
        }
    }
}

2、mapState的使用

  • 导入mapState

import {mapState} from 'vuex'
  • 必须在计算属性中使用扩展运算符来进行映射

语法

computed:{
    ...mapState(['state中的属性名'])
}

案例

export default {
    computed:{
        ...mapState(["shopcartList"])
    }
}
  • 组件中直接使用

{{shopcartList}}

3、mapMutations

  • 导入mapMutations

import {mapMutations} from 'vuex'
  • 必须在methods中使用扩展运算符的方式将其映射成组件中相关方法

export default {
    methods:{
        ...mapMutations(["increment_Sync"]),
        increment(){
            this.increment_Sync()
        }
    }
}

4、mapGetters

  • 导入mapGetters

import {mapGetters} from 'vuex'
  • 在computed选项中使用扩展运算符将其映射

export default {
    computed:{
        ...mapGetters(["totalPrice"])
    },
}

5、别名

如果你映射仓库中的名字正好和你的组件内的名子冲突了怎么办

export default{
    methods:{
        ...mapMutations({"新名称1":"仓库中名称"}),
        ...mapActions({"新名称1":"仓库中名称"})
    },
    compouted:{
        ...mapState({"新名称1":"仓库中名称"}),
        ...mapGetters({"新名称1":"仓库中名称"})
    }
}

总结:actions和mutations是在methods选项中映射的,state和getters是在computed选项中映射的。

五、vuex的模块化

随着项目的规模越来越大,状态机的功能越来越多的时候,我们仅仅将所有的功能写在store/index.js中,这样会带来如下的麻烦

  • 业务结构不够清晰

  • 可读性很差

  • 可维护性很差

1、模块的实现步骤

  • 在src/store文件夹下创建modules文件夹

  • 在modules文件下创建shopcart.js,内容如下

    特别注意:如果要模块化,必须要在该对象中设置namespaced:true

export default {
    namespaced:true,
    state: {
        shopcartList: []
    },
    mutations: {
        getShopcartList_Sync(state, payload) {
            console.log('------2、store中的mutations的getShopcartList_Sync--------------');
            console.log('payload', payload);
            state.shopcartList = payload
        }
    },
    actions: {
        async getShopcartList_Async(context) {
            console.log('------1、store中的actions的getShopcartListAsync--------------');
            let result = await Vue.prototype.$api.shopcart.getShopcartData()
            context.commit('getShopcartList_Sync', result.data)
        },
        async checkedProduct_Async(context, payload) {
            console.log('------1、store中的actions的checkedProduct_Async--------------', payload);
            let result = await Vue.prototype.$api.shopcart.checkProducts(payload)
            if (result.code) {
                //在actions中方法调用actions中的方法
                context.dispatch('getShopcartList_Async')
            }
        },
        async changeNum_Async(context, payload) {
            console.log('------1、store中的actions的changeNum_Async--------------', payload);
            let result = await Vue.prototype.$api.shopcart.changeNum(payload)
            if (result.code) {
                context.dispatch('getShopcartList_Async')
            }
        }
    },
    getters: {
        totalPrice: state => state.shopcartList.filter(item => item.checked).reduce((prev, cur) => prev + cur.price * cur.num, 0)
    }
}
  • 在store/index文件中引入该模块

import Vue from 'vue'
import Vuex from 'vuex'
import shopcart from './modules/shopcart'
import counter from './modules/counter'
Vue.use(Vuex)
const store=new Vuex.Store({
    state:{},
    mutations:{},
    actions:{},
    getters:{},
    modules:{
      a:shopcart,
      b:counter
    }
   
})
//导出store
export default store
  • 在组件中引用

    • 原生方式引入

    调用actions的方法

    this.$store.dispatch("模块名/actions的相关方法名")

    调用getters

    {{$store.getters['模块名/getters的相关名称']}}

    调用state

    {{$store.state.模块名.数据名}}

    调用mutations

     this.$store.commit('模块名/mutations的相关方法名')

    2、辅助函数访问模块化

辅助函数访问模块化的vuex的步骤

  • 导入createNamespacedHelpers

import {createNamespacedHelpers} from 'vuex'
  • 通过createNamespacedHelpers()来获取辅助函数

const {mapActions,mapState,mapGetters}=createNamespacedHelpers(模块名)

注意:如果在一个组件中要映射多个模块的辅助函数,就需要为每个模块的辅助函数取别名,解决命名冲突

const {mapActions:别名,mapState:别名,mapGetters:别名}=createNamespacedHelpers(模块名)
  • 在computed或者methods选项中通过扩展运算符实现映射

  methods:{
        ...mapShopcartActions(["getShopcartList_Async"]),
        ...mapCounterMutations(["increment_Sync"]),
  },
  computed:{
        ...mapShopcartState(["shopcartList"]),
        ...mapShopcartGetters(["totalPrice"]),
        ...mapCounterState(["num"])
  } 

六、vuex的持久化

vuex中的数据,一旦页面刷新之后会丢失?怎么处理?【回答】

由于vuex状态机中的数据是瞬时的, 保存在内存中的,所以页面刷新后,数据会丢失,如果要解决这个问题,需要将状态机中的数据进行持久化

不是所有的状态机的数据都需要持久化的

持久化的思路:持久化就是将vuex状态机中的数据保存在localStorage中存一份

1、使用vuex-persistedstate插件来实现vuex持久化

使用的步骤如下所示

  • 安装vuex-persistedstate依赖包

npm i vuex-persistedstate
  • 导入vue-persistestate

import createPersistedstate from 'vuex-persistedstate'
  • 在src/store/index.js在仓库入口文件中配置插件

const store=new Vuex.Store({
    //....省略
    plugins:[
      createPersistedstate({
        key:'store-num-key',
        paths:['b.num']
      })
    ]
})

七、用户信息

本项目需要在登录的时候,将用户信息保存到状态机中,便于后续的其他组件使用,下来首先安装和配置状态机

1、安装和配置vuex

  • 安装vuex@3.6.2的依赖包

  • 在store/index.js中编写基本架子

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store=new Vuex.Store({
    state:{},
    mutations:{},
    actions:{},
    getters:{},
    modules:{},
    plugins:[]
})
export default store
  • 在main.js文件中挂载store

import store from './store'
new Vue({
  render: h => h(App),
  store
}).$mount('#app')

2、登录的状态机配置

由于user的信息很多组件都要使用它,所以这里无需模块化

import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedstate from 'vuex-persistedstate'
Vue.use(Vuex)
const store=new Vuex.Store({
    state:{
        loginUser:{}
    },
    mutations:{
        SET_LOGINUSER(state,payload){
            state.loginUser=payload
        }
    },
    actions:{ 
        async getUserInfoAsync(cxt){
            console.log('---actions的getUserInfoAsync-----------');
            const result=await Vue.prototype.$api.users.getUserInfo()
            cxt.commit("SET_LOGINUSER",result.data)
        }  
    },
    getters:{},
    modules:{},
    plugins:[
        createPersistedstate({
            key:'USER_STORE',
            paths:["loginUser"]
        })
    ]
})
export default store

3、登录页面中向actions中的getUserInfoAsync派发

<script>
import {setStore} from '@/util/h5store'
import {TOKEN_KEY} from '@/util/constant'
import {mapActions} from 'vuex'
export default {
   
    methods:{
        ...mapActions({"guia":"getUserInfoAsync"}),
        login(){
            //在表单元素中有一个validate方法
            this.$refs.loginForm.validate(async args=>{
                
               if(args){
                 const {code,message,token}=await this.$api.users.login(this.userForm)
                 if(code){
                    //this.$message.success(message)
                    this.$message({
                        message,
                        type:'success'
                    })
                    //保存token
                    setStore(TOKEN_KEY,token)
                    //根据token来查询用户信息
                    //访问状态机中的异步方法来获取用户的信息
                    this.guia()
                    this.$router.replace('/')
                 }else{
                    this.$message.warning(message)
                 }
               }
            })

        }
    }
}
</script>

4、在Home.vue中获取用户信息

<el-avatar :src="loginUser.image"></el-avatar>

import {mapState} from 'vuex'
export default {
    computed:{
        ...mapState(["loginUser"])
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2. 两数相加

题目介绍 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都…

Hadoop 之 Hbase 配置与使用(四)

Hadoop 之 Hbase 配置与使用 一.Hbase 下载1.Hbase 下载 二.Hbase 配置1.单机部署2.伪集群部署&#xff08;基于单机配置&#xff09;3.集群部署1.启动 hadoop 集群2.启动 zookeeper 集群3.启动 hbase 集群4.集群启停脚本 三.测试1.Pom 配置2.Yml 配置3.Hbase 配置类4.Hbase 连…

LeetCode | Heap | 502.

502. IPO 是贪心算法in general。 一共两个变量&#xff1a;profit和capital。profit要求是找最大的。capital要求小于w。 两种筛选方法&#xff1a;把capital符合要求的排个序&#xff0c;找profit最大的。按照profit排序&#xff0c;从大到小找capital满足条件的。 哪种更…

flask结合mysql实现用户的添加和获取

1、数据库准备 已经安装好数据库&#xff0c;并且创建数据库和表 create database unicom DEFAULT CHARSET utf8 COLLATE utf8_general_ci; CREATE TABLE admin( id int not null auto_increment primary key, username VARCHAR(16) not null, password VARCHAR(64) not null…

C语言学习笔记 VScode设置C环境-06

目录 一、下载vscode软件 二、安装minGW软件 三、VS Code安装C/C插件 3.1 搜索并安装C/C插件 3.2 配置C/C环境 总结 一、下载vscode软件 在官网上下载最新的版本 Download Visual Studio Code - Mac, Linux, Windowshttps://code.visualstudio.com/download 二、安装minGW…

【Lua学习笔记】Lua入门

文章目录 Lua变量数据类型变量声明其他表示 Lua语法判断逻辑判断&#xff08;Lua很特殊&#xff0c;这个比较重要&#xff09;短路判断 ifif else 循环whileforrepeat 迭代器泛型for迭代器无状态迭代器多状态的迭代器 Lua函数select方法 数组字符索引_G &#xff08;不是教程&a…

毛绒玩具英国UKCA认证BS EN71检测

在2020年12月31日之后&#xff0c;欧盟统一标准将成为联合王国的“指定标准”&#xff0c;这类标准清单将由国务卿公布。 2021年1月1日&#xff0c;英国标准的实质内容将与欧盟采用的标准相同。 然而&#xff0c;他们将使用前缀“BS”来表示它们是 英国标准机构(BSI)作为英国国…

因数分解及统计(朴素版和优化版)--We Were Both Children(codeforces886 div4 F)

题目大意&#xff1a;就是有n个蛤蟆&#xff0c;他们可以必须每次跳a[i]个值的距离&#xff0c;而我们是负责捕捉的&#xff0c;肯定要找最多的相同点&#xff0c;这就相当于一个因数筛&#xff0c;看看这个筛中谁最多&#xff08;注意我们不可以在0点进行捕捉&#xff0c;并且…

网络安全作业1

URL编码 当 URL 路径或者查询参数中&#xff0c;带有中文或者特殊字符的时候&#xff0c;就需要对 URL 进行编码&#xff08;采用十六进制编码格式&#xff09;。URL 编码的原则是使用安全字符去表示那些不安全的字符。 安全字符&#xff0c;指的是没有特殊用途或者特殊意义的…

[RabbitMQ] RabbitMQ简单概述,用法和交换机模型

MQ概述&#xff1a; Message Queue(消息队列)&#xff0c;实在消息的传输过程中保存消息的容器&#xff0c;都用于分布式系统之间进行通信 分布式系统通信的两种方式&#xff1a;直接远程调用 和 借助第三昂 完成间接通信 发送方称谓生产者&#xff0c;接收方称为消费者 MQ优…

SpringBoot整合Druid

前提&#xff1a;在SpringBoot整合JDBC的基础上完成Druid的整合 SpringBoot整合JDBC 可参考--------> SpringBoot整合JDBC_Maiko Star的博客-CSDN博客 1. 添加Druid依赖 在pom.xml文件中添加Druid的依赖项。例如&#xff1a; <dependency><groupId>com.ali…

《面试1v1》Kafka的架构设计是什么样子

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

Audio2Face

1:下载链接。 Omniverse Enterprise 许可和定价 | NVIDIA 2:安装。 audio2face ue插件 教程&#xff1a; 1&#xff1a;【青松微课堂】Audio2Face数字人工作流&#xff1a;软件的下载安装与UI介绍 【青松微课堂】Audio2Face数字人工作流&#xff1a;软件的下载安装与UI介绍_…

vue3下的uniapp跨域踩坑

uniapp vue3 H5跨域踩坑 开发移动端H5的时候由于后端接口没有做跨域处理&#xff0c;因此需要做下服务器代理&#xff0c;于是百度搜索了uniapp下h5的跨域配置 在manifest下的h5配置proxy&#xff0c;大概是这样: "h5": {"devServer": {"https"…

分享几个水滴效果的按钮

先看效果&#xff1a; 再看代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>水滴效果的按钮</title><link rel"stylesheet" href"https://codepen.io/nico…

Python数据分析实战-datafram按某(些)列按值进行排序(附源码和实现效果)

实现功能 Python对datafram按某&#xff08;些&#xff09;列进行排序&#xff08;附源码和实现效果&#xff09; 实现代码 import pandas as pd# 读取数据 datapd.read_csv(E:\数据杂坛\\UCI Heart Disease Dataset.csv) dfpd.DataFrame(data) print(df.head())# # 按某列的…

桥梁安全生命周期监测解决方案

一、方案背景 建筑安全是人们生产、经营、居住等经济生活和人身安全的基本保证&#xff0c;目前我国越来越多的建筑物逐 步接近或者已经达到了使用年限&#xff0c;使得建筑物不断出现各种安全隐患&#xff0c;对居民的人身安全和财产安全产 生不利影响&#xff0c;因此房…

html基于onmouse事件让元素变颜色

最近&#xff0c;在书写div块时&#xff0c;遇到一个小问题&#xff0c;这个小问题我搞了将近一个小时多才慢慢解决。问题是这样子的&#xff0c;有一个div块&#xff0c;我想让鼠标移上去变成蓝色&#xff0c;移开变成灰色&#xff0c;当鼠标按下去时让他变成深蓝色。于是就单…

quartus工具篇——ROM ip核

quartus工具篇——ROM ip核 1、ROM简介 FPGA中的ROM(Read-Only Memory)是一种只读存储器,主要用来存储固化的初始化配置数据。FPGA ROM的特性主要有: 预编程初始化 - ROM在FPGA编程时就已经写入了初始值,这些值在整个工作周期保持不变。初始化配置 - ROM通常用来存储FPGA的初…

MySQL——主从复制

1.理解MySQL主从复制原理。 2.完成MySQL主从复制。 1.理解MySQL主从复制原理。 1&#xff09;、MySQL支持的复制类型 &#xff08;1&#xff09;、基于语句&#xff08; statement &#xff09;的复制 在主服务器上执行SQL 语句&#xff0c;在从服务器上执行同样的语句。 My…