当前位置: 首页 > news >正文

TypeScript 函数

函数是JavaScript应用程序的基础。 它帮助你实现抽象层,模拟类,信息隐藏和模块。 在TypeScript里,虽然已经支持类,命名空间和模块,但函数仍然是主要的定义 行为 的地方。 TypeScript为JavaScript函数添加了额外的功能,让我们可以更容易地使用。

在 TypeScript 中,函数是用于执行特定任务并可能返回结果的代码块。

函数类型

可以为函数定义类型来明确函数的参数类型和返回值类型。

// 有名字的函数
function sum(a: number, b: number): number {return a + b;
}
// 匿名函数
let mySum = function(x: number, y: number): number { return x + y; };

这里明确了 sum 函数接受两个 number 类型的参数 ab,并返回一个 number 类型的值。

书写完整函数类型

函数类型包含两部分:参数类型和返回值类型。 当写出完整函数类型的时候,这两部分都是需要的。

在函数和返回值类型之前使用( =>)符号。

返回值类型是函数类型的必要部分,如果函数没有返回任何值,必须指定返回值类型为 void 而不能留空。

let mySum: (x: number, y: number) => number =function(x: number, y: number): number { return x + y; };

在这段代码中:

  • let mySum: (x: number, y: number) => number 这部分定义了一个变量 mySum,并指定了它的类型为接受两个 number 类型参数并返回 number 类型值的函数类型。
  • 然后通过 function(x: number, y: number): number { return x + y; }mySum 变量赋值了一个具体的函数实现。

以参数列表的形式写出参数类型,为每个参数指定一个名字和类型:

let mySum: (a: number, b: number) => number =function(x: number, y: number): number { return x + y; };

在这段代码中,虽然函数定义中的参数名 ab 与函数实现中的参数名 xy 不同,但它们的类型都是 number,这是匹配的。

TypeScript 在类型检查时关注的是参数的类型,而不是参数的名称。只要参数的类型符合函数类型定义的要求,代码就可以通过类型检查。

在定义函数的类型时,只考虑参数的类型和返回值的类型。

函数中使用的捕获变量不会体现在类型里。 实际上,这些变量是函数的隐藏状态并不是组成API的一部分。
这是因为这些捕获变量属于函数的内部实现细节,对于使用该函数的外部代码来说,并不需要知道这些内部的状态。函数的 API 主要是通过其公开的参数和返回值来与外部进行交互和通信。
示例:

let outerValue = 10;function myFunction(x: number): number {let innerValue = 5;return x + outerValue + innerValue;
}

在上述 myFunction 函数中,outerValue 是捕获的外部变量,innerValue 是函数内部的变量,它们都不会体现在函数的类型 (x: number) => number 中。

推断类型

如果在赋值语句的一边指定了类型,但是另一边没有类型的话,TypeScript编译器会自动识别出类型:

let mySum = function(x: number, y: number): number { return x + y; };

在这个例子中,mySum 的类型会被推断为 (x: number, y: number) => number
在这里插入图片描述

可选参数和默认参数

JavaScript里,每个参数都是可选的,可传可不传。 没传参的时候,它的值就是undefined

TypeScript里的每个函数参数都是必须的。传递给一个函数的参数个数必须与函数期望的参数个数一致。

在 TypeScript 中,可选参数和默认参数为函数提供了更灵活的参数设置方式。

可选参数

通过在参数名后面添加 ? 来标记参数为可选参数。调用函数时,可以选择不传递该参数。
示例:

function printInfo(name: string, age?: number) {console.log(`Name: ${name}, Age: ${age ?? 'no age'}`);
}printInfo("张三");      // "Name: 张三, Age: no age"
printInfo("李四", 25);  // "Name: 李四, Age: 25" 
printInfo("王二", 0);   // "Name: 王二, Age: 0" 

可选参数必须跟在必须参数后面。
这是为了确保在调用函数时,必需的参数能够按照正确的顺序被传递,而不会因为可选参数的存在导致参数传递的混乱。

默认参数

可以为参数指定一个默认值,如果调用函数时没有传递该参数或传递的值是undefined时,就会使用默认值。

function printInfo(name: string, age: number = 18) {console.log(`Name: ${name}, Age: ${age}`);
}
printInfo("张三");      // "Name: 张三, Age: 18" 
printInfo("李四", 25);  // "Name: 李四, Age: 25" 
printInfo("王二", undefined);   // "Name: 王二, Age: 18" 

当一个参数在所有必需参数之后并且有默认初始化值时,它就具有了可选的性质。
printInfo 函数中,age 参数具有默认值 18 ,所以在调用函数时可以省略它,就像可选参数一样。

与普通可选参数不同的是,带默认值的参数不需要放在必须参数的后面。 如果带默认值的参数出现在必须参数前面,用户必须明确的传入 undefined值来获得默认值。
示例:

function printInfo(name: string = "张三", age: number) {console.log(`Name: ${name}, Age: ${age}`);
}
printInfo(undefined, 18);   // "Name: 张三, Age: 18" 
printInfo("李四", 25);      // "Name: 李四, Age: 25" // 假如只传入 age 
printInfo(25); // Error: Expected 2 arguments, but got 1.

剩余参数

必要参数、默认参数、可选参数有个共同点:它们表示某一个参数。
有时,想同时操作多个参数,或者并不知道会有多少参数传递进来。 在JavaScript里,你可以使用 arguments来访问所有传入的参数。

在 TypeScript 中,剩余参数用于表示不确定数量的参数。它使用 ... 语法来定义。
剩余参数会被当做个数不限的可选参数。 可以一个都没有,同样也可以有任意个。

function sumAll(numbers: number[], ...restNum: number[]) {let total = 0;for (const num of numbers) {total += num;}for (const num of restNum) {total += num;}return total;
}// 没有剩余参数
console.log(sumAll([1, 2, 3])); // 6// 有 3 个剩余参数
console.log(sumAll([1, 2, 3], 4, 5, 6));  // 21

在为带有剩余参数的函数定义类型时,也需要正确地表示剩余参数的部分。
实现 sumAll 函数的类型定义:

let myFunction: (numbers: number[], ...restNum: number[]) => number = sumAll;// 参数名字可以不一样,但是参数的类型必须一样
let myFunc: (nums: number[], ...rest: number[]) => number = sumAll;

this和箭头函数

在普通函数中,this 的值取决于函数的调用方式。如果是作为对象的方法被调用,this 指向该对象;如果是独立调用,非严格模式下,this 通常指向全局对象(在浏览器环境中是 window,在 Node.js 环境中是 global)。严格模式下, thisundefined

非严格模式下:

// 作为对象的方法被调用
let obj = {method: function() {console.log(this);  // 这里的 this 指向 obj 对象}
};
obj.method();// 独立调用
function standalone() {console.log(this);  // 在浏览器中,这里的 this 指向 window 对象
}
standalone();

严格模式下:

// 作为对象的方法被调用
let strictObj = {strictMethod: function() {"use strict";console.log(this);  // 这里的 this 指向 strictObj 对象}
};
strictObj.strictMethod();// 独立调用
function strictStandalone() {"use strict";console.log(this);  // 这里的 this 是 undefined
}
strictStandalone();

可以在浏览器中执行代码来验证结果。

箭头函数中的 this 继承自其定义时所在的上下文,不会因为调用方式的不同而改变。

let obj = {method: () => {// "use strict";console.log(this); // 在浏览器中,这里的 this 指向 window 对象}
};
obj.method();

这段代码中,无论是严格模式还是非严格模式,this 都指向 window 对象。
箭头函数 method 是在对象 obj 中定义的,由于是箭头函数,this 并不指向 obj ,而是继承了外部(即全局)的 this 值。在浏览器环境中,全局的 this 就是 window 对象。

使 this 指向obj

let obj = {width: 10,height: 10,method() {return () => {return console.log(this)}}
};
obj.method()();// 把obj.method()赋值给method变量
let method = obj.method();
method()

在这里插入图片描述
由上图运行结果可知,箭头函数里的 this 指向obj。此时,this 的 类型 是 any

this 参数

在 TypeScript 中,this 可以被显式地作为参数添加到函数的参数列表中,用于更明确地控制和处理函数内部的 this 指向。

提供一个显式的 this 参数, 让this 的类型不是any

interface OBJ {width: number;height: number;method(this: OBJ): () => number;
}let obj: OBJ = {width: 10,height: 10,method(this: OBJ) {return () => {return this.width + this.height}}
};
console.log(obj.method()()); // 20let method = obj.method(); 
console.log(method); // 20

这段代码中,thisOBJ 类型的。不论如何调用method()this始终指向OBJ

this参数在回调函数里

当把一个函数作为回调传递给库函数,并且在回调函数中使用了 this 时,确实经常会遇到 this 指向错误或为 undefined 的问题。
这是因为函数的调用方式会影响 this 的指向。如果回调函数被库函数以普通函数的方式调用,而不是作为对象的方法调用,那么 this 就不会指向预期的对象,通常会是 undefined
例如,假设有一个库函数 doAsyncOperation ,它接受一个回调函数:

function doAsyncOperation(callback: () => void) {// 模拟异步操作完成后调用回调setTimeout(callback, 1000);
}

然后有一个类 MyClass ,其中有一个方法想要在回调中使用 this

class MyClass {data: string = "Some data";performOperation() {doAsyncOperation(this.someCallback);}someCallback() {console.log(this.data);  // undefined}
}
let myC = new MyClass();
myC.performOperation();

执行myC.performOperation()语句, doAsyncOperation 内部以普通函数的方式调用 callback ,当 doAsyncOperation 调用回调函数时,this 不是指向 MyClass 的实例,而是 undefined ,导致无法访问 data 属性。回调函数的输出结果为undefined

因为在 setTimeout 内部,如果传递的回调函数是一个普通函数,那么 this 的指向取决于运行环境和调用方式。

在非严格模式下,如果是在浏览器环境中,this 通常指向 window 对象;在 Node.js 环境中,this 通常指向 global 对象。
在严格模式下,this 的值会是 undefined

someCallback 改为箭头函数:

class MyClass {data: string = "Some data";performOperation() {doAsyncOperation(this.someCallback);}someCallback = () => {console.log(this.data);  // "Some data"}
}
let myC = new MyClass();
myC.performOperation();

在上述代码中,someCallback 被定义为箭头函数。
箭头函数不会创建自己的 this 上下文,而是继承外层(即定义它的 MyClass 实例)的 this 上下文。
doAsyncOperation 函数中的异步操作完成并调用 callback (即 this.someCallback )时,由于 someCallback 是箭头函数,它所使用的 this 仍然是其定义时所在的 MyClass 实例的 this
所以,在 someCallback 函数内部,能够正确访问到 MyClass 实例的属性 data ,并将其打印出来,即输出结果为 “Some data” 。

或者:

class MyClass {data: string = "Some data";performOperation() {doAsyncOperation(() => this.someCallback());}someCallback() {console.log(this.data);  // "Some data"}
}
let myC = new MyClass();
myC.performOperation();

doAsyncOperation(() => this.someCallback()); 中,使用了一个立即执行的箭头函数。
箭头函数不会创建自己的 this 上下文,而是继承外层(即定义它的 MyClass 实例)的 this 上下文。
在这个箭头函数内部,this 正确地指向了 MyClass 的实例。

上面这个例子比较简单,再举一个复杂一点的例子。
例如,假设有一个库函数 UIElement ,库函数的作者要指定 this的类型:

interface UIElement {addClickListener(onclick: (this: void, e: CustomEvent,  params?: {[propName: string]: any}) => void): void;
}

有一个Handler类,处理自定义事件以及在不同类型的回调函数中处理数据和 this 的指向。

class Handler {info: string = "";onClickGood(this: void, e: CustomEvent) {// 通过指定 this: void ,表明该回调函数在被调用时不期望或不依赖于特定的 this 上下文。console.log(this); // undefinedconsole.log("clicked!");}onClickGood2 = (e: CustomEvent) => {// 箭头函数,this 指向 Handlerthis.info = e.detail.message;};doOther (this: void, e: CustomEvent, params?: {[propName: string]: any}) {// 在这里根据传入的 params 进行相应的处理// 如果要操作this,就使用箭头函数。console.log(e.detail.message);console.log(params);};
}let h = new Handler();
let uiElement: UIElement = {addClickListener(onclick) {const event = new CustomEvent("click", { detail: { message: "Hello" } });onclick(event);}
};uiElement.addClickListener(h.onClickGood);
uiElement.addClickListener(h.onClickGood2);let uiElementDo: UIElement = {addClickListener(onclick) {const event = new CustomEvent("click", { detail: { message: "输出用户的输入" } });let word = prompt("输入你想说的话", "");let params = {word: word}onclick(event, params);}
};uiElementDo.addClickListener(h.doOther)

函数重载

在 TypeScript 中,函数重载是指可以为同一个函数定义多个不同的签名(参数类型和返回类型的组合)。
示例:

function add(a: number, b: number): number;
function add(a: string, b: string): string;function add(a: any, b: any): any {if (typeof a === 'number' && typeof b === 'number') {return a + b;}if (typeof a ==='string' && typeof b ==='string') {return `${a} ${b}`;}throw new Error('Invalid parameters');
}console.log(add(1, 2));  // 3
console.log(add('hello', 'world')); // "hello world" 

在上述示例中,add 函数有两个不同的函数签名:一个接受两个数字参数并返回一个数字,另一个接受两个字符串参数并返回一个字符串。

函数的实现部分根据传入参数的类型来决定执行不同的逻辑。

相关文章:

TypeScript 函数

函数是JavaScript应用程序的基础。 它帮助你实现抽象层,模拟类,信息隐藏和模块。 在TypeScript里,虽然已经支持类,命名空间和模块,但函数仍然是主要的定义 行为 的地方。 TypeScript为JavaScript函数添加了额外的功能&…...

C++ : namespace,输入与输出,函数重载,缺省参数

一,命名空间(namespace) 1.1命名空间的作用与定义 我们在学习c的过程中,经常会碰到命名冲突的情况。就拿我们在c语言中的一个string函数来说吧: int strncat 0; int main() {printf("%d", strncat);return 0; } 当我们运行之后&…...

目标检测 | yolov1 原理和介绍

1. 简介 论文链接:https://arxiv.org/abs/1506.02640 时间:2015年 作者:Joseph Redmon 代码参考:https://github.com/abeardear/pytorch-YOLO-v1 yolo属于one-stage算法,仅仅使用一个CNN网络直接预测不同目标的类别与…...

excel中有些以文本格式存储的数值如何批量转换为数字

一、背景 1.1 文本格式存储的数值特点 在平时工作中有时候会从别地方导出来表格,表格中有些数值是以文本格式存储的(特点:单元格的左上角有个绿色的小标)。 1.2 文本格式存储的数值在排序时不符合预期 当我们需要进行排序的时候…...

原神升级计划数据表:4个倒计时可以修改提示信息和时间,可以点击等级、命座、天赋、备注进行修改。

<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><title>原神倒计时</title><style>* {margin: 0;padding: 0;box-sizing: border-box;body {background: #0b1b2c;}}header {width: 100vw;heigh…...

YoloV10 论文翻译(Real-Time End-to-End Object Detection)

​摘要 近年来&#xff0c;YOLO因其在计算成本与检测性能之间实现了有效平衡&#xff0c;已成为实时目标检测领域的主流范式。研究人员对YOLO的架构设计、优化目标、数据增强策略等方面进行了探索&#xff0c;并取得了显著进展。然而&#xff0c;YOLO对非极大值抑制&#xff0…...

第R1周:RNN-心脏病预测

本文为&#x1f517;365天深度学习训练营 中的学习记录博客 原作者&#xff1a;K同学啊 要求&#xff1a; 1.本地读取并加载数据。 2.了解循环神经网络&#xff08;RNN&#xff09;的构建过程 3.测试集accuracy到达87% 拔高&#xff1a; 1.测试集accuracy到达89% 我的环境&a…...

Golang | Leetcode Golang题解之第321题拼接最大数

题目&#xff1a; 题解&#xff1a; func maxSubsequence(a []int, k int) (s []int) {for i, v : range a {for len(s) > 0 && len(s)len(a)-1-i > k && v > s[len(s)-1] {s s[:len(s)-1]}if len(s) < k {s append(s, v)}}return }func lexico…...

远程连接本地虚拟机失败问题汇总

前言 因为我的 Ubuntu 虚拟机是新装的&#xff0c;并且应该装的是比较纯净的版本&#xff08;纯净是指很多工具都尚未安装&#xff09;&#xff0c;然后在使用远程连接工具 XShell 连接时出现了很多问题&#xff0c;这些都是我之前没遇到过的&#xff08;因为之前主要使用云服…...

WebRTC 初探

前言 项目中有局域网投屏与文件传输的需求&#xff0c;所以研究了一下 webRTC&#xff0c;这里记录一下学习过程。 WebRTC 基本流程以及概念 下面以 1 对 1 音视频实时通话案例介绍 WebRTC 的基本流程以及概念 WebRTC 中的角色 WebRTC 终端,负责音视频采集、编解码、NAT 穿…...

Python:read,readline和readlines的区别

在Python中&#xff0c;read(), readline(), 和 readlines() 是文件操作中常用的三个方法&#xff0c;它们都用于从文件中读取数据&#xff0c;但各自的使用方式和适用场景有所不同。 read() 方法&#xff1a; read(size-1) 方法用于从文件中读取指定数量的字符。如果指定了si…...

重生之我学编程

编程小白如何成为大神&#xff1f;大学新生的最佳入门攻略 编程已成为当代大学生的必备技能&#xff0c;但面对众多编程语言和学习资源&#xff0c;新生们常常感到迷茫。如何选择适合自己的编程语言&#xff1f;如何制定有效的学习计划&#xff1f;如何避免常见的学习陷阱&…...

如何将PostgreSQL的数据实时迁移到SelectDB?

PostgreSQL 作为一个开源且功能强大的关系型数据库管理系统&#xff0c;在 OLTP 系统中得到了广泛应用。很多企业利用其卓越的性能和灵活的架构&#xff0c;应对高并发事务、快速响应等需求。 然而对于 OLAP 场景&#xff0c;PostgreSQL 可能并不是最佳选择。 为了实现庞大规…...

关于c语言的const 指针

const * type A 指向的数据是常量 如上所示&#xff0c;运行结果如下&#xff0c;通过解引用的方式&#xff0c;改变了data的值 const type * A 位置是常量&#xff0c;不能修改 运行结果如下 type const * A 指针是个常量&#xff0c;指向的值可以改变 如上所示&#xff0c…...

万能门店小程序开发平台功能源码系统 带完整的安装代码包以及安装搭建教程

互联网技术的迅猛发展和用户对于便捷性需求的不断提高&#xff0c;小程序以其轻量、快捷、无需安装的特点&#xff0c;成为了众多商家和开发者关注的焦点。为满足广大商家对于门店线上化、智能化管理的需求&#xff0c;小编给大家分享一款“万能门店小程序开发平台功能源码系统…...

C#初级——字典Dictionary

字典 字典是C#中的一种集合&#xff0c;它存储键值对&#xff0c;并且每个键与一个值相关联。 创建字典 Dictionary<键的类型, 值的类型> 字典名字 new Dictionary<键的类型, 值的类型>(); Dictionary<int, string> dicStudent new Dictionary<int, str…...

git版本控制的底层实现

目录 前言 核心概念串讲 底层存储形式探测 本地仓库的详细解析 提交与分支的深入解析 几个问题的深入探讨 前言 Git的重要性 Git是一个开源的版本控制工具&#xff0c;广泛用于编程开发领域。它极大地提高了研发团队的开发协作效率。对于开发者来说&#xff0c;Git是一个…...

深入解析数据处理的技术与实践

欢迎来到我的博客,很高兴能够在这里和您见面!欢迎订阅相关专栏: 工💗重💗hao💗:野老杂谈 ⭐️ 全网最全IT互联网公司面试宝典:收集整理全网各大IT互联网公司技术、项目、HR面试真题. ⭐️ AIGC时代的创新与未来:详细讲解AIGC的概念、核心技术、应用领域等内容。 ⭐…...

python-调用c#代码

环境&#xff1a; win10&#xff0c;net framework 4&#xff0c;python3.9 镜像&#xff1a; C#-使用IronPython调用python代码_ironpython wpf-CSDN博客 https://blog.csdn.net/pxy7896/article/details/119929434 目录 hello word不接收参数接收参数 其他例子 hello word 不…...

构建铁路安全防线:EasyCVR视频+AI智能分析赋能铁路上道作业高效监管

一、方案背景 随着我国铁路特别是高速铁路的快速发展&#xff0c;铁路运营里程不断增加&#xff0c;铁路沿线的安全环境对保障铁路运输的安全畅通及人民群众的生命财产安全具有至关重要的作用。铁路沿线安全环境复杂多变&#xff0c;涉及多种风险因素&#xff0c;如人员入侵、…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...

GraphQL 实战篇:Apollo Client 配置与缓存

GraphQL 实战篇&#xff1a;Apollo Client 配置与缓存 上一篇&#xff1a;GraphQL 入门篇&#xff1a;基础查询语法 依旧和上一篇的笔记一样&#xff0c;主实操&#xff0c;没啥过多的细节讲解&#xff0c;代码具体在&#xff1a; https://github.com/GoldenaArcher/graphql…...