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>
相关文章
|
1天前
|
存储 JavaScript 开发者
Vue 组件间通信的最佳实践
本文总结了 Vue.js 中组件间通信的多种方法,包括 props、事件、Vuex 状态管理等,帮助开发者选择最适合项目需求的通信方式,提高开发效率和代码可维护性。
|
1天前
|
存储 JavaScript
Vue 组件间如何通信
Vue组件间通信是指在Vue应用中,不同组件之间传递数据和事件的方法。常用的方式有:props、自定义事件、$emit、$attrs、$refs、provide/inject、Vuex等。掌握这些方法可以实现父子组件、兄弟组件及跨级组件间的高效通信。
|
6天前
|
JavaScript
Vue基础知识总结 4:vue组件化开发
Vue基础知识总结 4:vue组件化开发
|
6天前
|
存储 JavaScript
Vue 状态管理工具vuex
Vue 状态管理工具vuex
|
12天前
|
缓存 JavaScript UED
Vue 中实现组件的懒加载
【10月更文挑战第23天】组件的懒加载是 Vue 应用中提高性能的重要手段之一。通过合理运用动态导入、路由配置等方式,可以实现组件的按需加载,减少资源浪费,提高应用的响应速度和用户体验。在实际应用中,需要根据具体情况选择合适的懒加载方式,并结合性能优化的其他措施,以打造更高效、更优质的 Vue 应用。
|
11天前
|
JavaScript
如何在 Vue 中使用具名插槽
【10月更文挑战第25天】通过使用具名插槽,你可以更好地组织和定制组件的模板结构,使组件更具灵活性和可复用性。同时,具名插槽也有助于提高代码的可读性和可维护性。
15 2
|
11天前
|
JavaScript
Vue 中的插槽
【10月更文挑战第25天】插槽的使用可以大大提高组件的复用性和灵活性,使你能够根据具体需求在组件中插入不同的内容,同时保持组件的结构和样式的一致性。
14 2
|
11天前
|
前端开发 JavaScript 容器
在 vite+vue 中使用@originjs/vite-plugin-federation 模块联邦
【10月更文挑战第25天】模块联邦是一种强大的技术,它允许将不同的微前端模块组合在一起,形成一个统一的应用。在 vite+vue 项目中,使用@originjs/vite-plugin-federation 模块联邦可以实现高效的模块共享和组合。通过本文的介绍,相信你已经了解了如何在 vite+vue 项目中使用@originjs/vite-plugin-federation 模块联邦,包括安装、配置和使用等方面。在实际开发中,你可以根据自己的需求和项目的特点,灵活地使用模块联邦,提高项目的可维护性和扩展性。
|
12天前
|
缓存 JavaScript UED
Vue 中异步加载模块的方式
【10月更文挑战第23天】这些异步加载模块的方式各有特点和适用场景,可以根据项目的需求和架构选择合适的方法来实现模块的异步加载,以提高应用的性能和用户体验
|
12天前
|
JavaScript 测试技术 UED
解决 Vue 项目中 Tree shaking 无法去除某些模块
【10月更文挑战第23天】解决 Vue 项目中 Tree shaking 无法去除某些模块的问题需要综合考虑多种因素,通过仔细分析、排查和优化,逐步提高 Tree shaking 的效果,为项目带来更好的性能和用户体验。同时,持续关注和学习相关技术的发展,不断探索新的解决方案,以适应不断变化的项目需求。
下一篇
无影云桌面