Vue3状态管理的使用详解

背景

随着Vue3的逐步应用,对状态管理的需求越来越多。起初是基于Vuex4进行状态管理的,但是Vuex4也暴露了一些问题。从个人角度来说,Vuex4类似于过渡期产品,对TypeScript的支持性并不完整。如果使用TypeScript编写组件,需要遵循一定步骤后,才可以正确进行类型推断,并且对modules的使用上也并不友好。Vuex核心贡献者Kia King也表示Vuex5已经在计划中,并且能提供完整的TypeScript支持,那么在Vuex5面世之前,或者直接"舍弃"Vuex的话有没有其他状态管理的方案?

Provide / Inject

provide和inject并不是Vue3的新特性,在Vue2中就已经存在了。文档中提到provide和inject绑定并不是可响应的。然而,如果你传入了一个可监听的对象,那么其对象的property还是可响应的。

Vue3在Computed与watch的基础上新增了响应性API ref和reactive,可以更加方便provide和inject的应用,再结合Composition API的思想,是否能实现一个简易版的状态管理?

抽离共享状态

// src/context/calculator.ts

import { ref, inject, provide, readonly } from 'vue';

type Calculator = {
    count: number;
    increase: () => void;
    updateCount: (num: number) => void;
};

//provide的key,唯一令牌
const CalculatorSymbol = Symbol();

//提供者
export const calculatorProvide = () => {
  	//数目
    const count = ref<number>(1);
  	//递增方法
    const increase = () => {
        count.value++;
    };
   //更新方法
    const updateCount = (num: number) => {
        count.value = num;
    };
  	//提供的共享状态对象
    const depends = {
        count: readonly(count), //状态只读,通过方法进行修改
        increase,
        updateCount
    };
  	//使用provide api实现状态对象提供
    provide(CalculatorSymbol, depends);
  	//返回状态对象,让同级可调用
    return depends;
};

//注入方法
export const calculatorInject = () => {
    //使用inject api注入状态
    const calculatorContext = inject<Calculator>(CalculatorSymbol);
  	//未共享就注入的错误校验
    if (!calculatorContext) {
        throw new Error('Inject must be used affer Provide');
    }
  	//返回注入的贡献状态
    return calculatorContext;
};

提供数据

相比起Vuex的全局共享,利用Provide / Inject可以实现全局或者局部共享,

全局共享,可以在main.ts中注入全局状态:

// src/main.ts

import { createApp, h } from 'vue';
import App from '@/App.vue';
import { calculatorProvide } from '@/context/calculator';

// 创建vue实例
const app = createApp({
    setup() {
        calculatorProvide();
        return () => h(App);
    }
});

// 挂载实例
app.mount('#app');

如果只想局部共享,可以在父组件中注入状态

// src/views/parent.vue

import { defineComponent } from "vue";
import { calculatorProvide } from '@/context/calculator';

export default defineComponent({
  name: "parent",
  setup() {
    //共享数据
    calculatorProvide();
  }
});

注入数据

子组件可以通过状态注入,使用或修改状态

// src/views/child.vue

import { defineComponent } from "vue";
import { calculatorInject } from '@/context/calculator';

export default defineComponent({
  name: "child",
  setup() {
    //注入数据
    const { count, increase, updateCount } = calculatorInject();
  }
});

小结

实际上,你可以将依赖注入(Provide / Inject)看作是"long range props",除了:

  • 父组件不需要知道哪些子组件使用它provide的property
  • 子组件不需要知道inject的property来自哪里

Vue3使依赖注入的使用更加灵活便捷,以此仿造了小型的状态管理,个人测试上,对TypeScript的支持性比较完整

reactive

那么不使用Provide / Inject,还有别的方法可以实现状态管理吗?直接上代码。

抽离共享状态

// src/context/calculator.ts

type Calculator = {
    count: number;
    increase: () => void;
    updateCount: (num: number) => void;
};

//共享状态
const calculatorStore = reactive<Calculator>({
    count: 1,
    increase: () => {
        calculatorStore.count++;
    },
    updateCount: (num: number) => {
        calculatorStore.count = num;
    }
});

export { calculatorStore };

使用共享状态

使用状态的方法很简单,只需要import状态即可,需要使用状态的组件,都需要导入

// src/views/any.vue

import { defineComponent } from "vue";
import { calculatorStore } from '@/context/calculator';

export default defineComponent({
  name: "any",
  setup() {
    console.log(calculatorStore.count);
  }
});

小结

其实这个方案利用的是reactive的响应性及import同一实例原理,相比起依赖注入来的更简单粗暴,也能正确支持TypeScript校验。但是依赖注入可以在不同根节点共享不同的数据,而这个reactive方案永远共享的是一个实例,在某些业务场景下并不适用。

结语

首先,Vuex仍旧是更成熟全面的方案,只是针对一些简单的状态管理,可以尝试换个思路解决;当然以上的方案可能还有很多考虑不全地方,欢迎各位大神指点指点~

以上就是Vue3状态管理的使用详解的详细内容,更多关于Vue3状态管理的使用的资料请关注我们其它相关文章!

(0)

相关推荐

  • vue store之状态管理模式的详细介绍

    状态管理 一.状态管理(vuex)简介 uex是专为vue.js应用程序开发的状态管理模式.它采用集中存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.vuex也集成刀vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试.状态快照导入导出等高级调试功能. Vuex 的思想 当我们在页面上点击一个按钮,它会处发(dispatch)一个action, action 随后会执行(commit)一个mutation, mut

  • Flutter部件内部状态管理小结之实现Vue的v-model功能

    Flutter部件内部状态管理 本文是 Flutter 部件内部状态管理的小结,从部件的基础开始,到部件的状态管理,并且在过程中实现一个类似 Vue 的 v-model 的功能. widget 基础 widget(部件) 如 React 里万物皆组件, Java 里万物皆对象, Flutter 里,能看到的一切都是 widget(部件),如按钮.文本框等等. Flutter 内部已经为我们做了一些基础的 widget ,例如: Text : 这个就是一个文本部件,里面用于放置文本 Row , C

  • 使用Vue.observable()进行状态管理的实例代码详解

    随着组件的细化,就会遇到多组件状态共享的情况, Vuex当然可以解决这类问题,不过就像 Vuex官方文档所说的,如果应用不够大,为避免代码繁琐冗余,最好不要使用它,今天我们介绍的是 vue.js 2.6 新增加的 Observable API ,通过使用这个 api 我们可以应对一些简单的跨组件数据状态共享的情况. 先看下官网描述,如下图 observable()方法,用于设置监控属性,这样就可以监控viewModule中的属性值的变化,从而就可以动态的改变某个元素中的值,监控属性的类型不变量而

  • 详解几十行代码实现一个vue的状态管理

    介绍 采用集中式存储管理应用的所有组件的状态, 就能实现组件间数据共享 实现 逻辑图 从图上有两条线: Vue.use(vuec), 与 new Vuec.center(options) 第一条线Vue.use(vuec)安装插件 使用Vue.use(vuec)时, 会执行vuec的install方法,会注入参数Vue 所以vuec是这样的, // index.js import {Center, install} from './center' export default {Center,

  • 说说如何使用Vuex进行状态管理(小结)

    1 为什么需要状态管理 一个 Vue 组件分为数据(model)与视图(view).当通过 methods 中的方法更新数据时,视图也会自动更新. message.vue <template> <div> {{message}} <button @click="changeMessage">改变内容</button> </div> </template> <script> export default

  • 40行代码把Vue3的响应式集成进React做状态管理

    前言 vue-next是Vue3的源码仓库,Vue3采用lerna做package的划分,而响应式能力@vue/reactivity被划分到了单独的一个package中. 如果我们想把它集成到React中,可行吗?来试一试吧. 使用示例 话不多说,先看看怎么用的解解馋吧. // store.ts import { reactive, computed, effect } from '@vue/reactivity'; export const state = reactive({ count:

  • vue.js的状态管理vuex中store的使用详解

    一.状态管理(vuex)简介 vuex是专为vue.js应用程序开发的状态管理模式.它采用集中存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.vuex也集成刀vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试.状态快照导入导出等高级调试功能. 二.状态管理核心 状态管理有5个核心,分别是state.getter.mutation.action以及module.分别简单的介绍一下它们: 1.state state为

  • vuex(vue状态管理)的特殊应用案例分享

    有需求才会有应用! 需求:vue项目中,我需要一个类似全局的变量保存一个tag的值,在不同层级下的子组件中,对这个变量进行修改,并且使变化的结果作用在组件页面上. 这里使用vuex解决问题,代码如下: import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); const state = { spinTag: false, //spin组件标记 }; //改变状态的方法 const mutations = { spinTagTAG(s

  • 在react中使用vue的状态管理的方法示例

    我是要介绍一个新的 react 全局共享状态管理器,它和 vue 组件的状态管理一起同工之妙. 马上体验 在 react 状态管理领域,react-redux 可谓是只手遮天了,基于 flux 思想实现,小巧,immutable 的思想让数据变化可控.但 immutable 所带来的编程代价太大了,如果你要更新一个深层结构的对象的某个节点,写作将会是极其麻烦的一件事,而且还保不准会出错.为了保证 immutable,redux 的 reducer 机制让开发者掉光了头发.于是有了类似 dva.r

  • Vue的状态管理vuex使用方法详解

    引入vuex 当访问数据对象时,一个 Vue 实例只是简单的代理访问.所以,如果有一处需要被多个实例间共享的状态,可以简单地通过维护一份数据来实现共享 const sourceOfTruth = {} const vmA = new Vue({ data: sourceOfTruth }) const vmB = new Vue({ data: sourceOfTruth }) 现在当 sourceOfTruth 发生变化,vmA 和 vmB 都将自动的更新引用它们的视图.子组件们的每个实例也会

随机推荐