Vue | Vue.js 全家桶 Vuex状态管理(一)

简介: Vue | Vue.js 全家桶 Vuex状态管理(一)

一、认识应用状态管理

什么是状态管理

       在开发中,我们会的应用程序需要处理各种各样的数据,这些数据需 要保存在我们应用程序中的某一个位置,对于这些数据的管理我们就 称之为是 状态管理。 


在前面我们是如何管理自己的状态呢


       在Vue开发中,我们使用组件化的开发方式;


       而在组件中我们定义data或者在setup中返回使用的数据,这些数 据我们称之为state;


       在模块template中我们可以使用这些数据,模块最终会被渲染成 DOM,我们称之为View;


       在模块中我们会产生一些行为事件,处理这些行为事件时,有可能 会修改state,这些行为事件我们称之为actions;


复杂的状态管理


       JavaScript开发的应用程序,已经变得越来越复杂了:


       JavaScript需要管理的状态越来越多,越来越复杂


       这些状态包括服务器返回的数据、缓存数据、用户操作产生的数据等等


       也包括一些UI的状态,比如某些元素是否被选中,是否显示加载动效,当前分页;


当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:


       多个视图依赖于同一状态


       来自不同视图的行为需要变更同一状态;


我们是否可以通过组件数据的传递来完成呢


       对于一些简单的状态,确实可以通过props的传递或者Provide的方式来共享状态


       但是对于复杂的状态管理来说,显然单纯通过传递和共享的方式是不足以解决问题的,比如兄弟组件如何共享数据呢?

Vuex的状态管理

管理不断变化的state本身是非常困难的:


       状态之间相互会存在依赖,一个状态的变化会引起另一个状态的变化,View页面也有可能会引起状态的变化


       当应用程序复杂时,state在什么时候,因为什么原因而发生了变化,发生了怎么样的变化,会变得非常难以控制和追踪;


可以将组件的内部状态抽离出来,以一个全局单例的方式来管理


       在这种模式下,我们的组件树构成了一个巨大的 “试图View”


       不管在树的哪个位置,任何组件都能获取状态或者触发行为


       通过定义和隔离状态管理中的各个概念,并通过强制性的规则来维护视图和状态间的独立性,我们的代码边会变得更加结构 化和易于维护、跟踪;


这就是Vuex背后的基本思想,它借鉴了Flux、Redux、Elm(纯函数语言,redux有借鉴它的思想)

VueX的状态管理图解

987242adcc5841c28be1eba4a2f33446.png

二、Vuex的基本使用

Vuex的安装

JavaScript

npm install vuex


创建Store

每个Vuex应用的核心就是store(仓库):


       store本质上是一个容器,它包含着你的应用中心大部分的状态(state)


Vuex和单纯的全局对象有什么区别?


第一:Vuex的状态存储是响应式的


       当Vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会被更新


第二:不能直接改变store中的状态


       改变store中的状态的唯一途径就显示 提交(commit)mutation


       这样使得我们可以方便的跟踪每一个状态的变化,从而让我们能够通过一些工具帮助我们更好的管理应用的状态


使用步骤:


       创建Store对象;


       在app中通过插件安装

组件中使用store

在组件中使用store,按照如下的方式:


       在模版中使用;


       在options api中使用 如 computed


       在setup中使用

单一状态树(概念)

Vuex使用单一状态数:


       用 一个对象 就包含了全部的应用层级的状态


       采用的是SSOT Single Source of Truch 也可以翻译成单一数据源


意味着,每个应用将仅仅包含一个store实例:


       但状态树和模块化并不冲突.


单一状态树的优势:


       如果你的状态信息是保存到多个Store对象中的,那么之后的管理和维护等都会变得特别困难


       所以Vuex也使用了单一状态数来管理应用层级的全部状态


       单一状态树能让我们 最直接的方式找到某个状态的片段


       而且在之后的维护和调试过程中,也可以非常方便的管理和维护

三、核心概念State

组件获取状态

在前面如果觉得那种方式有点繁琐(表达式过长),那么我们可以使用计算属性:


       如果我们有很多状态都需要获取的话,可以使用mapState的辅助函数


               mapState的方式一:对象类型;方式二:数组类型


               也可以使用 展开运算符和原有的computed 混合在一起

JavaScript
computed:{
            // 这样写 还是需要写三遍
            // name(){
            //     return this.$store.state.name
            // }
            // 返回的是一个一个的函数   
            //  名 称 冲 突  按数组方式映射过来 可能会导致 名字冲突
            ...mapState(["name","level","avatarURL"]),
            // 我们可以传入一个对象 自己来定义名字
            ...mapState({
                sName:state => state.name,
                sLevel:state => state.level
            })
        }

在setup中使用mapState

在setup中如果我们单个获取装是非常简单的:


       通过useStore拿到store后去获取某个状态即可;


       但是如果我们需要使用mapState的功能呢?


默认情况下,Vuex并没有提供非常方便的使用mapState的方式,我们进行了一个函数的封装


(封装了一个函数)

36826603e77b4072a0b895f2eb1f49eb.png

不使用封装函数的方法:

JavaScript
 // 2 直接对store.state进行解构
    const store = useStore()
    // 这里不是 响应式的
    // const { name,level } = store.state
    // 可以使用 toRefs来保证 他是一个响应式
    const { name,level } = toRefs(store.state)
    // 修改level 测试
    function changeLevel(){
        //  这里 违背了逻辑的  不推荐这样写
        // 正规写法为  store.commit("increment")
        store.state.level++
    }

四、核心概念Getters

getters的基本使用

某些属性可能需要经过变化后来使用,这个时候可以使用getters:

JavaScript
const store = createStore({
    // state(){
    //     return {
    //         counter:0
    //     }
    // }
    state:()=>({
        counter:100,
        name:"xiong",
        level:99,
        avatarURL:"http://xxxx",
        users:[
            { id:1,name:"xiong",age:18 },
            { id:2,name:"kobe",age:30 },
            { id:3,name:"james",age:25 }
        ]
    }),
    getters:{
        doubleCounter(state){
            return state.counter*2
        },
        // 需求, 求users里面所有用户的age和 ,年龄和  reduce累加
        totalAge(state){
            return state.users.reduce((preValue,item)=>{
                return preValue + item.age
            },0)
        },
        // 这里有第二值 就是 getters
        msg(state,getters){
            // 在getters属性中,获取其他的getters
            return `name:${state.name} level:${state.level} usersTotalAge:${getters.totalAge}`
        }
    },

647686017afc45e2994bc270e37aaffd.png

getters第二个参数

getters可以接收第二个参数

JavaScript
getters:{
        doubleCounter(state){
            return state.counter*2
        },
        // 需求, 求users里面所有用户的age和 ,年龄和  reduce累加
        totalAge(state){
            return state.users.reduce((preValue,item)=>{
                return preValue + item.age
            },0)
        },
        // 这里有第二值 就是 getters
        msg(state,getters){
            // 在getters属性中,获取其他的getters
            return `name:${state.name} level:${state.level} usersTotalAge:${getters.totalAge}`
        }
    },

getters的返回函数

getters中的函数本身,可以返回一个函数,那么在使用的地方相当于可以调用这个函数:

JavaScript
getters:{
    // 获取信息
    getusersById(state){
        return function(id){
            const user = state.users.find(item => item.id === id)
            return user
        }
    }
},
==========================
<h2>id-2的朋友信息: {{ $store.getters.getusersById(2) }}</h2>
mapGetters的辅助函数
这里我们也可以使用mapGetters的辅助函数
JavaScript
computed:{
    ...mapGetters(["doubleCounter","totalAge","getusersById"]),
  }

e4d279c35d0749e98801c2a4ca406a6e.png

mapGetters的辅助函数

这里我们也可以使用mapGetters的辅助函数

JavaScript

computed:{

    ...mapGetters(["doubleCounter","totalAge","getusersById"]),

  }

8ae49df31c564561ab3deef888862843.png

在setup中使用

JavaScript
<script setup>
import { computed,toRefs } from 'vue';
import { mapGetters,useStore } from 'vuex'
  const store = useStore()
  // mapGetters(["msg"]) => 返回的是一个对象
  // 这样做 还是有点麻烦
  const { msg:msgFn } =  mapGetters(["msg"])
  const msg = computed(msgFn.bind({ $store: store }))
  // 最终做法:
  // const { msg } = toRefs(store.getters)
  // 3 针对某一个getters属性使用computed
  // const msg = computed(()=> store.getters.msg)
</script>
相关文章
|
4月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
391 2
|
3月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
355 137
|
7月前
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
883 0
|
7月前
|
JavaScript UED
用组件懒加载优化Vue应用性能
用组件懒加载优化Vue应用性能
|
6月前
|
人工智能 JSON JavaScript
VTJ.PRO 首发 MasterGo 设计智能识别引擎,秒级生成 Vue 代码
VTJ.PRO发布「AI MasterGo设计稿识别引擎」,成为全球首个支持解析MasterGo原生JSON文件并自动生成Vue组件的AI工具。通过双引擎架构,实现设计到代码全流程自动化,效率提升300%,助力企业降本增效,引领“设计即生产”新时代。
518 1
|
6月前
|
JavaScript 安全
在 Vue 中,如何在回调函数中正确使用 this?
在 Vue 中,如何在回调函数中正确使用 this?
335 0
|
7月前
|
JavaScript 前端开发 开发者
Vue 自定义进度条组件封装及使用方法详解
这是一篇关于自定义进度条组件的使用指南和开发文档。文章详细介绍了如何在Vue项目中引入、注册并使用该组件,包括基础与高级示例。组件支持分段配置(如颜色、文本)、动画效果及超出进度提示等功能。同时提供了完整的代码实现,支持全局注册,并提出了优化建议,如主题支持、响应式设计等,帮助开发者更灵活地集成和定制进度条组件。资源链接已提供,适合前端开发者参考学习。
527 17
|
7月前
|
JavaScript 前端开发 UED
Vue 表情包输入组件实现代码及详细开发流程解析
这是一篇关于 Vue 表情包输入组件的使用方法与封装指南的文章。通过安装依赖、全局注册和局部使用,可以快速集成表情包功能到 Vue 项目中。文章还详细介绍了组件的封装实现、高级配置(如自定义表情列表、主题定制、动画效果和懒加载)以及完整集成示例。开发者可根据需求扩展功能,例如 GIF 搜索或自定义表情上传,提升用户体验。资源链接提供进一步学习材料。
347 1
|
7月前
|
存储 JavaScript 前端开发
如何高效实现 vue 文件批量下载及相关操作技巧
在Vue项目中,实现文件批量下载是常见需求。例如文档管理系统或图片库应用中,用户可能需要一次性下载多个文件。本文介绍了三种技术方案:1) 使用`file-saver`和`jszip`插件在前端打包文件为ZIP并下载;2) 借助后端接口完成文件压缩与传输;3) 使用`StreamSaver`解决大文件下载问题。同时,通过在线教育平台的实例详细说明了前后端的具体实现步骤,帮助开发者根据项目需求选择合适方案。
678 0
|
7月前
|
JavaScript 前端开发 UED
Vue 项目中如何自定义实用的进度条组件
本文介绍了如何使用Vue.js创建一个灵活多样的自定义进度条组件。该组件可接受进度段数据数组作为输入,动态渲染进度段,支持动画效果和内容展示。当进度超出总长时,超出部分将以红色填充。文章详细描述了组件的设计目标、实现步骤(包括props定义、宽度计算、模板渲染、动画处理及超出部分的显示),并提供了使用示例。通过此组件,开发者可根据项目需求灵活展示进度情况,优化用户体验。资源地址:[https://pan.quark.cn/s/35324205c62b](https://pan.quark.cn/s/35324205c62b)。
330 0