使用vue-hooks完成类似于React的useState

使用vue-hooks完成类似于React的useState

前言

在使用vue3的过程中,通常使用 ref()完成对应的响应式,但是在使用过程中我们需要使用.value来获取到真正的值,从而实现响应式,在开发过程中经常会忘记.value,本文主要是想解决一下类类似这方面的问题

对比React

使用React过程中,我们发现使用useState Hook给我们带来了很多便利的地方,通过useState,可以返回一个数组,并且从中可以结构出我们需要的响应式数据和对数据的修改方法

const [state,useState] = useState(0)

vue3的联想

现在我们使用的是vue3,我们是否可以写出类似的Hooks来完成对这方面的优化呢?答案是可以的。Vue3中提出了composition API,实现了组合式API,对比与Option API,Composition API

  • 其代码更易读,更易理解和学习,没有任何幕后操作
  • Composition API的好处不仅仅是以不同的方式进行编码,更重要的是对于代码的重用
  • 不受模板和组件范围的限制,也可以准确的知道我们可以使用哪些属性
  • 由于幕后没有什么操作,所以编辑器可以帮助我们进行类型检查和建议

所以我们可以试试是否可以写出对应的Hooks在Vue3的基础上,对Ref进行二次封装

准备工作

创建vite项目,我们使用的vue3-ts

在命令行输入

npm create vite@latest // 安装vite

按下回车我们选择 vue3-ts,并且按下回车,进行安装,安装成功之后进入项目目录

npm i //安装依赖

构建项目架构

在这里插入图片描述
在src目录中添加一个文件夹Hooks,我们将在里面完成我们对应个Hooks操作

在Hooks文件夹中创建index.ts文件,用于导出我们写好的hooks

/*
 * @Author: liming-pan
 * @Date: 2022-04-27 13:02:21
 * @LastEditors: liming-pan
 * @FilePath: \vue-hooks\src\hooks\index.ts
 */
import useState from "./useState";
import useReducer from "./useReducer";
import useReactive from "./useReactive";

export { useReactive, useState, useReducer };

现在我们开始对useState进行构思

参考React中的useState,会返回一个响应式的数以及对响应式数据的操作方法朝着这个目标我们开始写代码

/*
 * @Author: liming-pan
 * @Date: 2022-04-27 13:04:34
 * @LastEditors: liming-pan
 * @FilePath: \vue-hooks\src\hooks\useState\index.ts
 */

import { Ref, ref } from "vue";

const states: Ref[] = [];
const stateSetters: Array<any> = [];

let stateIndex: number = 0;

/**
 * 主要用于创建一个响应式的数据
 * @param initalState 初始state
 * @param stateIndex state对应的下标
 * @returns 判断已有数组中是否存在,如果不存在,则返回这个数据,如果存在了则就返回原有数据中对应的数据
 */
function createState<T>(initalState: T, stateIndex: number) {
  const state = ref<T>(initalState);

  return states[stateIndex] !== undefined ? states[stateIndex] : state;
}

/**
 * 完成函数的返回
 * @param stateIndex 传入state对应的下标
 * @returns 根据类型进行判断,如果是方法,则执行后的结构赋值给响应式的数据,如果不是函数类型,那么我们就将传递过来的新的值的进行赋值
 */
function createStateSetters(stateIndex: number) {
  return function (newState: any) {
    if (typeof newState === "function") {
      states[stateIndex].value = newState(states[stateIndex]);
    } else {
      states[stateIndex].value = newState;
    }
  };
}

/**
 * useState Hooks
 * @param initalState 暴露出去的方法,在外界使用时,仅需传入初始值
 * @returns 返回一个响应式的数据,以及返回一个可以对数据进行操作的操作函数
 */
function useState<T>(initalState: T) {
  states[stateIndex] = createState(initalState, stateIndex);
  if (!stateSetters[stateIndex]) {
    stateSetters.push(createStateSetters(stateIndex));
  }

  const _state = states[stateIndex];
  const _setState = stateSetters[stateIndex];

  stateIndex++;
  return [_state, _setState];
}

export default useState;

总结

在这里我们就完成了对应的useStateHooks的完成我们在组件进行测试

<!--
 * @Author: liming-pan
 * @Date: 2022-04-27 12:57:22
 * @LastEditors: liming-pan
 * @FilePath: \vue-hooks\src\App.vue
-->
<script setup lang="ts">
import { useState } from "./hooks";
const [count1, setCount1] = useState<number>(0);
</script>

<template>
  <div>
    <div>
      <h1>{{ count1 }}</h1>
      <button @click="setCount1((count: any) => count.value + 1)">ADD</button>
      <button @click="setCount1(count1 - 1)">JIAN</button>
    </div>
  </div>
</template>

<style></style>

测试结果为
在这里插入图片描述

完成我们想要得到的Hooks效果,在经过Hooks并没有丢失其响应式同时也在某种程度上减少了.value的书写,增加了数据的可读性

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值