写点什么

不习惯的 Vue3 起步五 のapiHooks 封装

作者:空城机
  • 2022 年 7 月 13 日
  • 本文字数:1672 字

    阅读完需:约 5 分钟

不习惯的 Vue3 起步五 のapiHooks封装

使用请求 Hooks 完善业务

在前端开发过程中,对于 Api 接口通常会进行封装,这里 vue3 中因为添加了 typescript,所以也再来写写。


本次接口使用的是网上找的公开 api:https://tenapi.cn/zhihuresou/,请求出来的数据是知乎热搜榜


返回数据格式:

{  "data": 200,  "list": [    {      "name": "lpl",      "query": "FPX 不敌 iG 遭淘汰",      "url": "https://www.zhihu.com/search?q=lpl&utm_content=search_hot&type=content"    }  ]}
复制代码

fetch 请求封装

  1. 在项目 src 文件夹下创建一个hooks文件夹,然后创建一个index.ts文件和useApi.ts文件。在useApi.ts文件中主要编写 api 访问方法


  1. useApi.ts文件,创建一个useApi方法,此方法的输出结果受泛型控制,并且传入两个参数,url 和 options。


该方法内部的 url 请求是使用了fetch请求, RequestInfoRequestInit类型不需要额外定义,这是 ts 里本身就有的


对于抛出方式,可以选择两种都写,这样外部使用时可选性会广一些。


方法中用了泛型,<T>可以帮助捕获用户传入的类型,T 可以赋值给之后传入参数 value 和返回值,来作为它们的类型。

function useApi<T>(url: RequestInfo, options?: RequestInit) {    const response:Ref<undefined | T> = ref();    const request = async () => {        const res = await fetch(url, options);        const data = await res.json();        response.value = data;    }    return {        response,        request    }}// 两种抛出方式export default useApi;export {    useApi}
复制代码


  1. 这里可以设置一个接口,作为useApi方法返回的类型接口


export type ApiRequest = ()=>Promise<void>;export interface UsableAPI<T> {    response:Ref<undefined | T>,    request: ApiRequest}
复制代码


  1. 在切换到 hooks 目录下的 index.ts,这是此文件夹的入口文件,外部要调用 hooks 内部的所有方法,都需要通过 index.ts 获取


在 index.ts 中添加 export { useApi } from './useApi';




quicktype

从接口获取到数据,在 ts 往往也需要将其转换为类型模型,这样之前的泛型中才能使用


可以自己依旧数据来写,也可以使用quicktype快速生成


quicktype 从 JSON、JSON 模式、TypeScript 和 GraphQL 查询生成强类型模型和序列化程序,使在许多编程语言中安全地使用 JSON 类型变得轻而易举。 仓库:https://github.com/quicktype/quicktype


我选择了全局安装: npm install -g quicktype, 如果图方便,可以直接使用网页https://app.quicktype.io/来进行生成


全局安装完成后,在 vs code 终端中打开要生成 ts 接口类型文件的对应 models 文件夹,然后输入命令:quicktype 接口地址 -o 文件名称.ts


在刚刚创建的 models 文件 zhihu.ts 中,可以编写一个模型方法,用于调用数据。此方法中通过引用之前写好的 useApi 方法获取接口数据

import { useApi } from '@/hooks'import { Ref, ref } from 'vue';export default async function useZhihu():Promise<Ref<Zhihu>> {    const { response: result, request } = await useApi<Zhihu>('https://tenapi.cn/zhihuresou/');    // 发起一次请求    const loaded = ref(false)    if (loaded.value === false) {        await request();        loaded.value = true;    }    return result;}
复制代码



vue 组件中调用

在子组件中调用起来比较简单,直接引入使用即可,并且可以直接await调用方法。在上面template中渲染时,也和 vue2 的用法相同。


<template>    <ul class="zhihu">        <li v-for="(item) in res.list">{{ item.name }}</li>    </ul></template>
<script setup lang="ts"> import useZhihu from '@/models/zhihu'
const res = await useZhihu();</script>
复制代码


不过,当运行程序后,会发现界面并不显示,这是因为异步组件,界面需要使用Suspense包裹,这是 vue3 新出的特性

<Suspense>    <template #default>        <apihookTest></apihookTest>    </template>    <template #fallback>    loading...    </template></Suspense>
复制代码


效果:




至此,基于 vue3 + typescript 的简单 apihooks 封装就已经结束了

发布于: 刚刚阅读数: 4
用户头像

空城机

关注

曾经沧海难为水,只是当时已惘然 2021.03.22 加入

业余作者,在线水文 主要干前端的活,业余会学学python 欢迎各位关注,互相学习,互相进步

评论

发布
暂无评论
不习惯的 Vue3 起步五 のapiHooks封装_Vue3_空城机_InfoQ写作社区