vue3.x系列之封装响应式的hooks技巧

v3.x封装一个接口请求的hooks的,都应该很熟练了,那么要实现一个响应式的hooks该怎么做?

实现效果

代码实现

js 复制代码
<template>
  <div v-if="error">Oops! Error encountered: {{ error.message }}</div>
  <div v-else-if="data">
    Data loaded:
    <pre>{{ data }}</pre>
  </div>
  <div v-else>Loading...</div>
  <button @click="url = 'https://jsonplaceholder.typicode.com/todos/2'">发送</button>
</template>

<script setup>
import { useFetch } from "@/hooks/useFetch";
import { ref } from "vue";
let url = ref("https://jsonplaceholder.typicode.com/todos/1");
const { data, error } = useFetch(url);
</script>
js 复制代码
import { delay } from "lodash-es";
import { ref, watchEffect, toValue } from "vue";

export function useFetch(url) {
  const data = ref(null);
  const error = ref(null);
  function fetchData() {
    fetch(toValue(url))
      .then((res) => res.json())
      .then((res) => {
        delay(() => {
          data.value = res;
        }, 2000);
      })
      .catch((err) => (error.value = err));
  }
  watchEffect(() => {
    fetchData();
  });
  return { data, error };
}

技巧总结

  • 这里我们传入的是一个url接口的ref,不是普通的字符串数据
  • hooks里面接收的时候,接口请求使用toValue转为普通的字符数据
  • watchEffect监听副作用,当ref数据变化时,及时响应来发起新的请求
  • delay方法模拟接口请求延时效果,区分出请求中的状态

v3.x的几个工具方法isRef,unref,toRef的对比

js 复制代码
// isRef  判断是否是ref类型
let url = ref("https://jsonplaceholder.typicode.com/todos/1");
const str = "hello world";
console.log(isRef(url), "isRef");
console.log(isRef(str), "isRef");
js 复制代码
// unref 解包ref
const unRefUrl = unref(url);
console.log("unRefUrl", unRefUrl);
console.log(unref(str), "unRefStr");
js 复制代码
// toRef 包装ref,可以将值、refs 或 getters 规范化为 refs (3.3+)。
const toRefUrl = toRef(url);
console.log("toRefUrl", toRefUrl);
console.log(toRef(str), "toRefStr");
js 复制代码
const state = reactive({
  foo: 1,
  bar: 2
});
const foo = toRef(state, "foo");

const foo1 = ref(state.foo);

上面这个 ref 不会和 state.foo 保持同步,因为这个 ref() 接收到的是一个纯数值。

  • toRef和ref的区别如下图
相关推荐
ywf121526 分钟前
前端的dist包放到后端springboot项目下一起打包
前端·spring boot·后端
恋猫de小郭34 分钟前
2026,Android Compose 终于支持 Hot Reload 了,但是收费
android·前端·flutter
hpoenixf7 小时前
2026 年前端面试问什么
前端·面试
还是大剑师兰特7 小时前
Vue3 中的 defineExpose 完全指南
前端·javascript·vue.js
泯泷7 小时前
阶段一:从 0 看懂 JSVMP 架构,先在脑子里搭出一台最小 JSVM
前端·javascript·架构
mengchanmian8 小时前
前端node常用配置
前端
华洛8 小时前
利好打工人,openclaw不是企业提效工具,而是个人助理
前端·javascript·产品经理
xkxnq8 小时前
第六阶段:Vue生态高级整合与优化(第93天)Element Plus进阶:自定义主题(变量覆盖)+ 全局配置与组件按需加载优化
前端·javascript·vue.js
A黄俊辉A9 小时前
vue css中 :global的使用
前端·javascript·vue.js
小码哥_常9 小时前
被EdgeToEdge适配折磨疯了,谁懂!
前端