vue3 项目封装vuex的mapxxx, 以及封装请求库

vuex mapxxx

在vue3的setup中是没有this的,所以我们可以通过vuex提供的useStore来获取store,那辅助函数mapState这些呢?应该其返回的都是函数,且在setup总并没有绑定this,自然也没有store对象,所以我们如果像vue2一样直接使用会报错。

封装 mapActions

我按照vue2的方式使用mapActions,会出现,$store $dispatch不存在的报错,因为setup中没有帮我们绑定this,自然拿不到this. $ store,所以才会报错,解决办法就是手动得其绑定store。
在这里插入图片描述
我们可以在中间包一层,获取所有的action然后手动绑上store在返回。使用
在这里插入图片描述
其使用稍稍为不同,需要加上模块名。
mutations跟actions是一样的,便不再列出。

封装mapState

因为mapState返回的是一个函数,vue2的话我们是在计算函数中使用它。所以vue3我们要使用计算属性,其返回一个ref的值。
在这里插入图片描述
首先根据类型判断是获取哪个模块的辅助函数,接着封装useMapper
在这里插入图片描述
使用就是
const { data } = useState(’’, [‘data’])
返回的就是一个对象,其每个属性的值比如data,都是一个ref对象。

封装useAsync请求库

封装一个类似于react的ahooks的useRequest的函数
在这里插入图片描述
基本思路是将其发送请求的状态,loading啥的都控制在一起,然后返回给调用的组件使用。
这样在外部就不用定义很多loading,data了。
因为vue3的响应式是reactive,所以要创建一个响应式对象。
比较神奇的是ts,
通过传入的参数request,只要在外部定义该函数的入参是什么类型,如上图的U[],ts就会自动判定,该U是啥类型,所以该函数所有的U就是该类型。不用说在useAsync<x,x>的时候还要给其传入泛型,因为定义的时候已经定义好了,如
在这里插入图片描述
ts会自动根据定义的loginApi的入参啊,返回的值类型啊,去定义useAsync中的T,U,而不需要使用useAsync的时候再传一遍。比如useAsync<x,x>这样。
下面是完整代码:

import { reactive, UnwrapRef, toRefs } from "vue";

import { ResProps } from "@/servies/axios";

interface StateProps<T> {
  data: T | undefined;
  error: Error | null;
  loading: boolean;
}

const initState: StateProps<null> = {
  data: null,
  error: null,
  loading: false,
};

const useAsync = <T extends any, U = unknown>(
  request: (...args: U[]) => Promise<ResProps<UnwrapRef<T>>>,
  options: {
    onSuccess?: (data: UnwrapRef<T>) => void;
    onError?: (error: Error) => void;
  } = {}
) => {
  const state = reactive<StateProps<T>>(initState as StateProps<T>);
  const { onSuccess, onError } = options;

  const setSuccess = (data: UnwrapRef<T>) => {
    state.data = data;
    state.error = null;
    state.loading = false;
  };

  const setError = (error: UnwrapRef<Error>) => {
    state.error = error;
    state.loading = false;
  };

  const run = async (...arg: U[]) => {
    if (!state.loading) {
      state.loading = true;
    }
    return await request(...arg)
      .then((res) => {
        onSuccess && onSuccess(res.data);
        setSuccess(res.data);
        return Promise.resolve(res.data);
      })
      .catch((err) => {
        setError(err);
        onError && onError(err);
        return Promise.reject(err);
      });
  };

  return { run, ...toRefs(state) };
};

export { useAsync };

可以尝试下自己封装些东西,对ts的认识以及对封装的概念很有帮助。

vue3的逻辑封装

写vue3d的时候也是体验了一把vue3的逻辑封装,如图
在这里插入图片描述
这是一个login组件,其逻辑全被封装到useLogin这个hooks了。在这里插入图片描述
这样就可以每个功能对应一个Hooks,不会像vue2一样所有都要放在一起。有点像react的写法。

改进

在之后的实践中,我发现这种写法在这里插入图片描述
ts检测有问题,比如
在这里插入图片描述
返回的对象的属性只要是字符串类型都行,什么意思呢?如
在这里插入图片描述
使用的时候,明明之传入三个,但却可以输入解构a,b却不报错,通过了ts的检测,证明我们的写法有问题,在这里插入图片描述
不能只简简单单这样定义返回的对象,因为args为string[],自然在这里插入图片描述
该对象的ts定义就类似于Record<string, ActionMethod>这样。不行的,我们必须根据传入的具体值来确定返回的类型,稍作改进之后
在这里插入图片描述

现在我们可以接受一个泛型入参T,它必须是string类型的,但是这个T的具体实现可以通过传入的数组的值来推导而出。
现在看效果
在这里插入图片描述
必须是你传入什么就是什么在这里插入图片描述

返回的对象的定义也是根据T来的了,所以现在你传入什么值就会对应输出什么值。在这里插入图片描述
useMapper的封装也要改。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coderlin_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值