前端开发攻略---一篇文章让你快速上手TypeScript

news2024/9/20 7:54:50

目录

1、TypeScript简介

2、为何需要TypeScript

2.1 今非昔比的JavaScript

2.2 JavaScript中的困扰

2.3 静态类型检查

3、编译TypeScript

3.1 命令行编译

3.2 自动化编译

4、类型声明

5、类型推断

6、类型总览

6.1 JavaScript中的数据类型

6.2 TypeScript中的数据类型

6.3 注意点

7、常用类型

7.1 any

7.2 unknown

7.3 never

7.4 void

7.5 object

7.5.1 object小写

7.5.2 Object大写

7.5.3 声明对象类型

7.5.3 声明函数类型

7.5.3 声明数组类型

7.6 tuple

7.7 enum

7.7.1 数字枚举

7.7.2 字符串枚举

7.7.3 常量枚举

7.8 type

7.9 一个特殊情况

7.10 抽象类

7.11 interface

8、自定义类型

9、抽象类

10、接口


1、TypeScript简介

1、TypeScript 由微软开发,是基于 JavaScript 的一个扩展语言

2、TypeScript 包含了JavaScript的所有内容,即TypeScript 是JavaScript 的超集

3、TypeScript 增加了:静态类型检查、接口、泛型等很多现代开发特性,因此更适合大型项目的开发。

4、TypeScript 需要编译为 JavaScript ,然后交给浏览器或其他 JavaScript 运行环境执行。

2、为何需要TypeScript

2.1 今非昔比的JavaScript

  • JavaScript 当年诞生时的定位是浏览器脚本语言,用于在网页中嵌入一些简单的逻辑,而且代码量很少。
  • 随着时间的推移,JavaScript 变得越来越流行,如今的 JavaScript 已经可以全栈编程了
  • 现如今的 JavaScript 应用场景比当年丰富的多,代码量也比当年大很多,随便一个 JavaScript 项目的代码量,可以轻松的达到几万行,甚至十几万行!
  • 然而 JavaScript 当年“出生简陋”,没考虑到如今的应用场景和代码量,逐渐的就出现了很多困扰。

2.2 JavaScript中的困扰

1、不清不楚的数据类型

2、有漏洞的逻辑

3、访问不存在的属性

4、低级的拼写错误

2.3 静态类型检查

  • 在代码运行前进行检查,发现代码的错误或不合理之处,减小运行时异常的出现的几率,此种检查叫『静态类型检查』,TypeScript 和核心就是『静态类型检查』,简言之就是把运行时的错误前置
  • 同样的功能,TypeScript 的代码量要大于JavaScript,但由于 TypeScript 的代码结构更加清晰,在后期代码的维护中 TypeScript 却远胜于JavaScript.

3、编译TypeScript

浏览器不能直接运行 TypeScript 代码,需要编译为 JavaScript 再交由浏览器解析器执行。

3.1 命令行编译

1、创建一个index.ts文件:例如:

2、全局安装TypeScript

npm i typescript -g

3、使用命令将ts文件编译为js文件

tsc index.ts

3.2 自动化编译

1、创建TypeScript编译控制文件

tsc --init
  1. 工程中会生成一个tsconfig.json的配置文件,其中包含着很多编译时的配置
  2. 观察发现,默认编译的JS版本是ES7,可以手动调整为其他版本

2、监视目录中的ts文件的变化

tsc --watch

3、优化:当编译出错时不生成js文件

tsc --noEmitOnError --watch

备注:也可以直接修改tsconfig.json中的noEmitOnError配置

4、类型声明

let a: string
let b: number
let c: boolean
let d: 'xxx'

a = '123'
b = 123
c = true
d = 'xxx'


function count(x: number, y: number): number {
    return x + y
}
console.log(count(1, 2));
// count(1)
// count(1, 2, 3)



5、类型推断

6、类型总览

6.1 JavaScript中的数据类型

  1. string
  2. number
  3. boolean
  4. null
  5. undefined
  6. bigint
  7. symbol
  8. object

备注:其中 object 包含:Arrary、Function、Date、Error等......

6.2 TypeScript中的数据类型

1、上述所有JavaScript类型

2、六个新类型

  1. any
  2. unknown
  3. never
  4. void
  5. tuple
  6. enum

3、两个用于自定义类型的方式

  1. type
  2. interface

6.3 注意点

在 Javascript 中的这些内置构造函数:Number、String、Boolean,它们用于创建对应的包装对象,在日常开发时很少使用,在 TypeScript 中也是同理,所以在 Typescript 中进行类型声明时,通常都是用小写的 number、string、boolean

let str1: string  // TS官方推荐的写法
str1 = '123'
// str1 = new String()  报错:不能将类型“String”分配给类型“string”。“string”是基元,但“String”是包装器对象。如可能首选使用“string”。


let str2: String
str2 = '123'
str2 = new String('123')

1、原始类型VS包装对象

  1. 原始类型:如number、string、boolean,在JavaScript中是简单数据类型,它们在内存中占用空间少,处理速度快
  2. 包装对象:如Number对象、String对象、Boolean对象,是复杂类型,在内存中占用更多空间,在日常开发时很少由开发人员自己创建包装对象

2、自动装箱:JavaScript在必要时会自动将原始类型包装成对象,以便调用方法或访问属性

// 原始类型字符串
let str = 'hello'

// 当访问str.length时 JavaScript引擎做了以下工作

let size = (function () {
    // 1、自动装箱:创建一个临时的String对象包装原始字符串
    let tempStringObject = new String(str)
    // 2、访问String对象的length属性
    let lengthValue = tempStringObject.length
    // 3、销毁临时对象,返回长度值
    // JavaScript引擎自动处理对象销毁 开发者无感
    return lengthValue
})()

console.log(size); // 5

7、常用类型

7.1 any

any的含义是:任意类型,一旦将变量类型限制为any,那就意味着放弃了对该变量的类型检查

let str: any
str = '123'
str = 123
str = true

注意点:any类型的变量可以赋值给任意类型的变量

let a: any
a = '123'
a = 123
a = true

let b: string
b = a // 无警告

7.2 unknown

unknow的含义是:未知类型,可以理解为一个类型安全的any,适用于:不确定数据的具体类型

// 设置a的类型为unknow
let a: unknown

a = 99
a = '123'
a = true

let b: string
// b = a 报错:不能将类型“unknown”分配给类型“string”。

unknow 会强制开发者在使用之前进行类型检查,从而提供更强的类型安全性

// 设置a的类型为unknow
let a: unknown

a = 99
a = '123'
a = true

let b: string

// 第一种
if (typeof a === 'string') {
    b = a
}
// 第二种(断言)
b = a as string

// 第三种(断言)
b = <string>a

读取any类型数据的任何属性都不会报错,二unknow正好与之相反

let str1: string
str1 = '123'
str1.toUpperCase() // 无警告

let str2: any
str2 = '123'
str2.toUpperCase() // 无警告


let str3: unknown
str3 = '123'
str3.toUpperCase() // 警告:“str3”的类型为“未知”。

// 使用断言强制指定str3的类型为string
(str3 as string).toUpperCase() // 无警告

7.3 never

never的含义是:任何值都不是,简而言之就是不能有值,undefined、null、''、0都不行!

1、几乎不用never去直接限制变量,因为没有意义,例如

let a: never
// 一下对a的所有赋值都会有警告
a = 1
a = true
a = '123'

2、never一般是TypeScript主动推断出来的,例如

let a: string

a = '123'

if (typeof a === 'string') {
    console.log(a.toUpperCase());
} else {
    console.log(a);  // TypeScript会推断出此处的a是nerve 因为没有任何一个值符合此处的逻辑
}

3、never也可以用于限制函数的返回值


// nerve一般作用域函数。表示该函数不能正常运行完毕。或者一直在运行
function a(): never {
    throw new Error('程序报错')
}

7.4 void

1、void通常用于函数返回值声明,含义:函数不返回任何值,调用者也不应依赖其返回值进行任何操作

function abc(str: string): void {
    console.log(str);
    // return 13 // 不能将类型“number”分配给类型“void”。
}
abc('hh')

注意:编码者没有编写return去指定函数的返回值,所以abc函数是没有显示返回值的,但会有一个隐式返回值,就是undefined;即:虽然函数返回类型为void,但也是可以接受undefined的,简单记:undefined是void可以接受的一种‘空’

2、以下写法均符合规范

function abc(str: string): void {
    console.log(str);
}
function abc1(str: string): void {
    console.log(str);
    return
}
function abc2(str: string): void {
    console.log(str);
    return undefined
}

3、返回值类型为void的函数,调用者不应依赖其返回值进行任何操作

function abc(str: string): void {
    console.log(str);
}

const result = abc('hhh')
if (result) { // 无法测试 "void" 类型的表达式的真实性。

}

function abc1(str: string): undefined {
    console.log(str);
    return undefined
}
const result1 = abc1('hhh')
if (result1) { // 无警告

}

4、理解void和undefined

  1. void 是一个广泛的概念,用来表达“空”,而 undefined 则是这种“空”的具体实现之一。
  2. 因此可以说 undefined 是 void 能接受的“空”状态的一种具体形式。
  3. 换句话说: void 包含 undefined ,但 void 表达的语义超越了单纯的 undefined ,它是一种意图上的约定,而不仅仅是特定值的限制。

5、总结:若函数返回类型为 void ,那么:

  1. 从语法上讲:函数是可以返回 undefined 的,至于显示返回,还是隐式返回,这无所谓!
  2. 从语义上讲:函数调用者不应关心函数返回的值,也不应依赖返回值进行任何操作!即使返回了 undefined 值

7.5 object

7.5.1 object小写

object(小写)的含义是:所有非原始类型,可存储:对象、函数、数组等,由于限制的范围比较宽,在实际开发中使用的相对较少

let a: object  // a能存储的类型是【非原始类型】
let b: Object

a = {}
a = []
a = function () { }
a = new String('123')
class Person { }
a = new Person()

a = 1 // 警告:不能将类型“number”分配给类型“object”。
a = true// 警告:不能将类型“boolean”分配给类型“object”
a = '你好'// 警告:不能将类型“string”分配给类型“object”。
a = null// 警告:不能将类型“null”分配给类型“object”
a = undefined// 警告:不能将类型“undefined”分配给类型“object”

7.5.2 Object大写

  1. 官方描述:所有可以调用Object方法的类型
  2. 简单记忆:除了undefined和null的任何值都能存
  3. 由于限制的范围太大了,实际开发中使用频率极低
let a: object  // a能存储的类型是【非原始类型】
let b: Object  // b能存储的类型是可以调用到Object方法的类型

b = {}
b = []
b = function () { }
b = new String('123')
class Person { }
b = new Person()
b = 1
b = true
b = '你好'
b = null // 警告:不能将类型“null”分配给类型“object”
b = undefined // 警告:不能将类型“undefined”分配给类型“object” */

7.5.3 声明对象类型

1、实际开发中:限制一般对象,通常使用一下形式

// 写法1
let person1: {
    name: string
    age?: number
}
// 写法2
let person2: { name: string, age?: number }
// 写法3
let person3: { name: string; age?: number }


person1 = { name: '张三', age: 99 }
person1 = { name: '张三' }

2、索引签名:允许定义对象可以具有任意数量的属性,这些属性的类型可变的,常用于:描述类型不确定的属性(具有动态属性的对象)

let person1: {
    name: string
    age?: number
    // 索引签名,可以添加任意数量的属性
    [key: string]: any
}

person1 = { name: '张三', age: 99, height: 100, city: '北京' }

7.5.3 声明函数类型

let count: (x: number, y: number) => number

count = function (x, y) {
    return x + y
}

备注:

  1. TypeScript中的=>在函数类型声明时表示函数类型,描述其参数类型返回类型
  2. JavaScript中的=>是一种定义函数的语法,是具体的函数实现
  3. 函数类型声明还可以使用:接口、自定义类型等方式

7.5.3 声明数组类型

let arr1: string[]
let arr2: Array<number>  // arr2是数组,并且里面的每一个元素都是number类型
arr1 = ['2', '1']
arr2 = [1, 2]

7.6 tuple

元组(Tuple)是一种特殊的数组类型,可以存储固定数量的元素,并且每个元素的类型是已知的可以不同,元组用于精确描述一组值的类型,?表示可选元素

// 第一个类型必须是string类型 第二个元素必须是number类型
let arr1: [string, number]

// 第一个元素必须是number类型,第二个元素是可选的,如果存在,必须是boolean类型
let arr2: [number, boolean?]

// 第一个元素必须是number类型,后面的元素可以是任意数量的string类型
let arr3: [number, ...string[]]

arr1 = ['123', 1]
// 警告:不能将类型“[string]”分配给类型“[string, number]”。源具有 1 个元素,但目标需要 2 个。
arr1 = ['123']
arr2 = [1]
arr2 = [1, true]
arr3 = [1, '1', '2']
// 警告:不能将类型“[number, string, string, number]”分配给类型“[number, ...string[]]”。源中位置 1 到 3 的类型与目标中位置 1 的类型不兼容。能将类型“number”分配给类型“string”。
arr3 = [1, '1', '2', 3] 

7.7 enum

枚举(enum)可以定义一组命名常量,它能增强代码的可读性,也让代码更好维护

如下代码的功能是:根据调用walk时传入的不同参数,执行不同的逻辑,存在的问题是调用walk时传参时没有任何提示,编码者很容易写错字符串内容;并且用于判断逻辑的up、down、left、right是连续且相关的一组值,那此时就特别适合使用枚举(enum)

function walk(str: string) {
    if (str === 'up') {
        console.log('上');
    } else if (str === 'down') {
        console.log('下');
    } else if (str === 'left') {
        console.log('左');
    } else if (str === 'right') {
        console.log('右');
    }else{
        console.log('其他情况');
    }
}
walk('up')
walk('down')
walk('left')
walk('right')

7.7.1 数字枚举

数字枚举是一种常见的枚举类型,其成员的值会自动递增,且数字枚举还具备反向映射的特点,可以通过值来获取对应的枚举成员名称

enum Direction {
    up,
    down,
    left,
    right
}
Direction.up = 99 // 警告:无法为“up”赋值,因为它是只读属性。

console.log(Direction.up); // 0
console.log(Direction.down); // 1
console.log(Direction.left); // 2
console.log(Direction.right); // 3

// 还具有反向映射的特点
console.log(Direction[0]); // up
console.log(Direction[1]); // down
console.log(Direction[2]); // left
console.log(Direction[3]); // right

function walk(str: Direction) {
    if (str === Direction.up) {
        console.log('上');
    } else if (str === Direction.down) {
        console.log('下');
    } else if (str === Direction.left) {
        console.log('左');
    } else if (str === Direction.right) {
        console.log('右');
    } else {
        console.log('其他情况');
    }
}


walk(Direction.up)
walk(Direction.down)
walk(Direction.left)
walk(Direction.right)

7.7.2 字符串枚举

会丢失反向映射

enum Direction {
    up = 'up',
    down = 'down',
    left = 'left',
    right = 'right'
}

let dir: Direction = Direction.up
console.log(dir); // 输出:up

7.7.3 常量枚举

官方描述:常量枚举是一种特殊枚举类型,它使用const关键字定义,在编译时会被内联,避免生成一些额外的代码

何为编译时内联?

所谓“内联”其实就是 TypeScript 在编译时,会将枚举成员引用替换为它们的实际值,而不是生成额外的枚举对象。这可以减少生成的 JavaScript 代码量,并提高运行时性能。

使用普通枚举的TypeScript代码如下,编译后生成的JavaScript代码量较大

enum Direction {
    up,
    down,
    left,
    right
}

let x = Direction.up
console.log(x);



// 以下是ts转换为js的代码
"use strict";
var Direction;
(function (Direction) {
    Direction[Direction["up"] = 0] = "up";
    Direction[Direction["down"] = 1] = "down";
    Direction[Direction["left"] = 2] = "left";
    Direction[Direction["right"] = 3] = "right";
})(Direction || (Direction = {}));
let x = Direction.up;
console.log(x);

使用常量枚举的TypeScript代码如下,编译后生成的JavaScript代码量较小

const enum Direction {
    up,
    down,
    left,
    right
}

let x = Direction.up
console.log(x);

// 以下是ts转换为js的代码
"use strict";
let x = 0 /* Direction.up */;
console.log(x);

7.8 type

7.9 一个特殊情况

7.10 抽象类

7.11 interface

8、自定义类型

9、抽象类

10、接口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2035170.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【模电笔记】——信号的运算和处理电路(含电压比较器)

tips&#xff1a;本章节的笔记已经打包到word文档里啦&#xff0c;建议大家下载文章顶部资源&#xff08;有时看不到是在审核中&#xff0c;等等就能下载了。手机端下载后里面的插图可能会乱&#xff0c;建议电脑下载&#xff0c;兼容性更好且易于观看&#xff09;&#xff0c;…

Python实战项目:天气数据爬取+数据可视化(完整代码)

一、选题的背景 随着人们对天气的关注逐渐增加&#xff0c;天气预报数据的获取与可视化成为了当今的热门话题&#xff0c;天气预报我们每天都会关注&#xff0c;天气情况会影响到我们日常的增减衣物、出行安排等。每天的气温、相对湿度、降水量以及风向风速是关注的焦点。通过…

搭建高可用OpenStack(Queen版)集群(十一)之OpenStack集成ceph服务

一、OpenStack集成ceph服务 一&#xff09;Openstack集成Ceph准备 1、OpenStack存储知识 1、OpenStack数据存储分类 Openstack环境中&#xff0c;数据存储可分为临时性存储与永久性存储。 临时性存储&#xff1a;主要由本地文件系统提供&#xff0c;并主要用于nova虚拟机的本地…

开放式耳机哪种好用又实用?五款爆火单品推荐

现在市面上的开放式耳机真的参差不齐&#xff0c;而且想要挑选到一款适合自己的开放式耳机&#xff0c;那真的很难&#xff0c;要做很多功课&#xff0c;现在购物就像是在大海捞针一样&#xff0c;所以我们该怎么挑选才能选到一款适合自己的开放式耳机呢&#xff1f;这个问题相…

数据库原理面试-核心概念-问题理解

目录 1.数据库、数据库系统与数据库管理系统 2.理解数据独立性 3.数据模型 4.模式、外模式和内模式 5.关系和关系数据库 6.主键与外键 7.SQL语言 8.索引与视图 9.数据库安全 10.数据库完整性 11.数据依赖和函数依赖 12.范式&#xff1f;三范式&#xff1f;为什么要遵…

Java基础11:JavaDoc生成文档

本节内容教学视频连接&#xff1a;https://www.bilibili.com/video/BV12J41137hu?p32&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5https://www.bilibili.com/video/BV12J41137hu?p32&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 1.什么是JavaDoc&#xff1f; Javado…

双向重发布实验

要求&#xff1a; 1. 如图搭建网络拓扑&#xff0c;所有路由器各自创建一个环回接 口&#xff0c;合理规划 IP 地址 2.R1-R2-R3-R4-R6 之间使用 OSPF 协议&#xff0c; R4-R5-R6 之间使用 RIP 协议 3.R1 环回重发布方式引入 OSPF 网络 4.R4/R6 上进行双点双向重发布 5. …

开发效率翻倍攻略!大学生电脑小白管理秘籍,资料秒搜技巧大公开!C盘满了怎么办?如何快速安全的清理C盘?烦人的电脑问题?一键解决!

如何正确管理自己的第一台电脑&#xff1f;大一新生如何管理自己的电脑&#xff1f;老鸟如何追求快捷操作电脑&#xff1f; 文章目录 如何正确管理自己的第一台电脑&#xff1f;大一新生如何管理自己的电脑&#xff1f;老鸟如何追求快捷操作电脑&#xff1f;前言初级基础分区操…

我开源了一个新项目! Product Hunt 每日中文热榜

Product Hunt 每日中文热榜 大家好&#xff0c;今天非常兴奋地与大家分享一个我刚刚开源的新项目 —— producthunt-daily-hot。这个项目从构思到实现仅花了 1 天时间&#xff0c;希望对大家有所帮助。Product Hunt 每日热榜 已上线&#xff0c;榜单会在每天下午 4 点自动更新…

学习记录——day30 网络编程 端口号port 套接字socket TCP实现网络通信

目录 一、端口号 port 二、套接字 socket 1、原理 2、socket函数介绍 三、TCP实现网络通信 1、原理 2、TCP通信原理图 3、TCP相关函数 1&#xff09;bind 绑定 2&#xff09;listen 监听 3&#xff09;accept 接收连接请求 4&#xff09;recv 接收 5&#xff09;sen…

GitHub的常用操作

目录 GitHub GitHub加速 克隆GitHub上的项目到本地 克隆GitHub上指定分支的项目 把本地项目上传到GitHub上管理 删除分支里的内容 单个仓库管理多个项目 上传项目到新建的分支 目前正在逐步熟悉GitHub&#xff0c;打算把整理好的代码上传到GitHub上&#xff0c;建立属…

EasyRecovery17中文版本重磅发布更新!带你三分钟了最新功能

“你到底删了我什么&#xff1f;&#xff1f;” “我只是把聊天记录清理了下……” “你知不知道里面还有我发你的工作资料啊&#xff01;&#xff01;” …… 每当听到这种对话&#xff0c;我就知道又有人因为删错文件而和另一半/同事/领导吵起来了。 毕竟在这个手机电脑不离手…

超声波清洗机哪个牌子好?四款公认最好的超声波清洗机分享

随着生活水平的提高&#xff0c;人们对于生活有了更高的要求&#xff0c;而我们平时经常使用的一些小产品也要经常清理保持干净&#xff0c;所以针对于这些小产品&#xff0c;超声波清洁机应运而生。超声波清洗机&#xff0c;可能很多小伙伴见过或者使用过&#xff0c;它主要利…

多模态大语言模型的免训练视觉提示学习 ControlMLLM

ControlMLLM: Training-Free Visual Prompt Learning for Multimodal Large Language Models github paper 在本研究中&#xff0c;提出了一种无需进行训练的方法&#xff0c;通过可学习的潜变量优化将视觉提示注入到多模态大型语言模型&#xff08;MLLMs&#xff09;中。 在…

PPSSPP Gold 1.17 psp模拟器黄金版最新免费修改版

这是您在安卓设备上体验原汁原味PSP游戏魅力的最佳选择——唯一正版的PSP模拟器。借助它&#xff0c;您可以在高清画质下畅玩PSP游戏&#xff0c;并享受额外的功能特性。大多数游戏都能流畅运行&#xff0c;不过具体表现还需视您的设备性能而定&#xff0c;部分游戏可能无法达到…

【数据结构与算法】哈希表——字符串匹配

目录 一.引入二.哈希表结构三.SDBMHash算法(字符->数字)★四.哈希表的算法实现1.哈希函数2.初始化3.查找4.插入5.删除6.获取数据7.销毁 五.完整代码1.头文件2.源文件3.运行结果 一.引入 原来我们讲的都是以整数作为关键码,那么我们可不可以用字符串来作为关键码呢? 有的时…

如何选择适合自己的编程语言,为什么R是非计算机专业数据分析的最佳选择,五大点告诉你

在如今的数据驱动世界中&#xff0c;编程语言已成为希望在行业中进行数据分析的专业人士不可或缺的技能。对于非计算机专业背景的学者和学生来说&#xff0c;选择适合自己的编程语言可能看似困难。本文将探讨为什么对于那些需要进行本科生论文、研究生论文、或者发表学术成果的…

4款伪原创文章生成器软件,为创作者在线生成原创文章

在当今内容创作需求旺盛的时代&#xff0c;创作者们常常面临着时间紧迫、灵感枯竭等挑战。而伪原创文章生成器软件的出现&#xff0c;为创作者们提供了一定的帮助。以下将为你详细介绍4款具有特色的伪原创文章生成器软件。 1、智媒ai伪原创工具 对于创作者来说&#xff0c;这款…

redis模块和ioredis的注意事项

redis模块和ioredis的注意事项 文章目录 redis模块和ioredis的注意事项前言一、ioredis和redis使用zrange的比较二、出现zrange结果不同的原因总结 前言 node.js在使用redis的时候有两个库可以选择&#xff0c;一个是redis、另一个是ioredis&#xff0c;我一直以来也没有太大关…

小红书js逆向x-s之补环境

请求参数分析 数据文件在homefeed里&#xff0c;直接复制header参数在Convert curl commands 生成python代码跑一下 &#xff08;注意curlconverter生成的respond的输入参数里有一个是json&#xff0c;这个是不对的&#xff0c;需要改为data&#xff09; 结果发现报错&…