TypeScript进阶

news2024/12/28 3:30:20

目录

TypeScript 与 Vue

文档说明

vscode 插件说明

准备页面基本结构

defineProps与Typescript

defineEmits与Typescript

ref与Typescript

reactive与Typescript

computed与Typescript

事件对象与Typescript

模板Ref与Typescript

可选链操作符和非空断言


TypeScript 与 Vue

文档说明

英文文档:TypeScript with Composition API | Vue.js

中文文档:TypeScript 与组合式 API | Vue.js

vscode 插件说明

 vue3 配合 ts 中,还需要额外安装一个 vscode 插件:Typescript Vue Plugin (Volar)

 

准备页面基本结构

main.ts

import { createApp } from 'vue'

import App from './App.vue'

const app = createApp(App)

app.mount('#app')

App.vue

<script setup lang="ts">

</script>

<template>

  <div>

    <h1>我是 App 组件</h1>

  </div>

</template>

defineProps与Typescript

目标:掌握 defineProps 如何配合 ts 使用

defineProps js 写法

App.vue

<script setup lang="ts">

import Child from './components/Child.vue'

import { ref } from 'vue'

const money = ref(100)

</script>

<template>

  <div style="border: 3px solid #ccc;margin: 10px;">

    <h1>我是 App 组件 --- {{ money }}</h1>

    <Child :money="money"></Child>

  </div>

</template>

components/Child.vue

<script setup lang="ts">

defineProps({

  money: {

    type: Number, // 定义类型

    required: true, // 是否必传

    // default: 10 // 默认值

  }

})

</script>

<template>

  <div style="border: 3px solid #ccc;margin: 10px;">

    <h3>我是 Child 组件 --- {{ money }}</h3>

  </div>

</template>

defineProps ts 写法

通过 defineProps 函数的泛型,指定了 prop 的名字和类型。(vue 内部做了一些处理)

components/Child.vue

<script setup lang="ts">

// 1. 只要写在泛型里面的 prop 类型,就代表是必填的了

defineProps<{

  money: number

}>()

// 2. 如果 prop 不是必传的

defineProps<{

  money?: number

}>()

// 3. 通过解构指定默认值

const { money = 10 } = defineProps<{

  money?: number

}>()

</script>

<template>

  <div style="border: 3px solid #ccc;margin: 10px;">

    <h3>我是 Child 组件 --- {{ money }}</h3>

  </div>

</template>

如果提供的默认值需要在模板中渲染,需要额外添加配置

Reactivity Transform | Vue.js

vite.config.ts

export default {

  plugins: [

    vue({

      reactivityTransform: true

    })

  ]

}

defineEmits与Typescript

目标:掌握 defineEmit 如何配合 ts 使用

defineEmits js 写法

App.vue

<script setup lang="ts">

import { ref } from 'vue'

import Child from './components/Child.vue'

const money = ref(100)

// 挣钱

const makeMoney = (childMoney: number) => {

  money.value = money.value + childMoney

}

</script>

<template>

  <div style="border: 3px solid #ccc;margin: 10px;">

    <h1>我是 App 组件</h1>

    <Child :money="money" @makeMoney="makeMoney"></Child>

  </div>

</template>

components/Child.vue

<script setup lang="ts">

const emit = defineEmits(['makeMoney'])

const makeMoney = () => {

  emit('makeMoney', 10)

}

</script>

<template>

  <div style="border: 3px solid #ccc;margin: 10px;">

    <h3>我是 Child 组件 --- {{ money }}</h3>

    <button @click="makeMoney">挣钱</button>

  </div>

</template>

defineEmits ts 写法

js 的写法只是接收了传递过来的自定义事件的名字。

通过 defineEmits 函数的泛型:指定了自定义事件的名字,还指定了自定义事件函数的参数和返回值的类型。(vue 内部做了一些处理)

<script setup lang="ts">

// defineEmits 传入对象类型,对象类型中是一个一个的匿名函数类型,这个对象类型不是用来直接给自定义事件数据定义的

// vue内部拿这个对象类型后要做组装处理,然后给父组件传递过来的自定义事件数据定义类型

// 语法

// const emit = defineEmits<{

//   (e: '自定义事件名', 自定义事件函数参数: 自定义事件函数参数类型): 自定义事件函数返回值类型

// }>()

const emit = defineEmits<{

  (e: 'makeMoney', childMoney: number): void

}>()

const makeMoney = () => {

  emit('makeMoney', 10)

}

</script>

<template>

  <div style="border: 3px solid #ccc;margin: 10px;">

    <h3>我是 Child 组件 --- {{ money }}</h3>

    <button @click="makeMoney">挣钱</button>

  </div>

</template>

指定类型的好处:使用 emit 触发自定义事件时,不会传错参数。

ref与Typescript

目标:掌握 ref 配合 ts 如何使用

  1. 如果是简单数据类型,通过泛型指定值的类型,并且该类型可以省略

App.vue

<script setup lang="ts">

import { ref } from 'vue'

const money = ref<number>(100)

// 相当于

const money = ref(100)

</script>

<template>

  <div>

    <h1>我是 App 组件 --- {{ money }}</h1>

  </div>

</template>

2.如果是复杂数据类型,通过泛型指定值的类型,并且推荐指定类型

App.vue

<script setup lang="ts">

import { ref } from 'vue'

// 不指定类型,会报错,并且没有提示

type User = {

  id: number

  name: string

  age: number

}

const list = ref<User[]>([])

// 模拟后端返回数据

setTimeout(() => {

  list.value = [

    { id: 1, name: 'zs', age: 18 },

    { id: 2, name: 'ls', age: 19 }

  ]

}, 1000)

</script>

<template>

  <div>

    <h1>我是 App 组件</h1>

  </div>

</template>

reactive与Typescript

目标:掌握 reactive 配合 ts 如何使用

App.vue

<script setup lang="ts">

import { reactive } from 'vue'

// reactive 只适用于给具有明确属性的复杂数据。它可以自己推断类型,所以不需要指定类型

const user = reactive({

  id: 1,

  name: 'zs',

  age: 18

})

// 如果指定类型,有两种写法

type User = {

  id: number

  name: string

  age?: number

}

// 写法一

const user: User = reactive({

  id: 1,

  name: 'zs',

  age: 18

})

// 写法二(泛型)

const user = reactive<User>({

  id: 1,

  name: 'zs',

  age: 18

})

</script>

<template>

  <div>

    <h1>我是 App 组件</h1>

  </div>

</template>

computed与Typescript

目标:掌握 computed 配合 typescript 如何使用

通过泛型可以指定 computed 计算属性返回值的类型,通常可以省略,因为它可以根据计算属性的返回值类型自动推导出来。

App.vue

<script setup lang="ts">

import { ref, computed } from 'vue'

const count = ref(100)

const doubleCount = computed(() => {

  return count.value * 2

})

const doubleCount = computed<number>(() => {

  return count.value * 2

})

</script>

<template>

  <div>

    <h1>我是 App 组件 --- {{ count }} --- {{ doubleCount }}</h1>

  </div>

</template>

事件对象与Typescript

目标:掌握事件对象配合 typescript 如何使用

App.vue

<script setup lang="ts">

// 1. 想要有事件对象上的属性提示,需要给事件对象指定类型(可以通过鼠标悬停到绑定的事件上,查看事件对象的类型)

const handleChange = (event: Event) => {

  console.log(event.target)

}

// 1. 想要有事件目标源上的属性提示,需要给事件目标源做类型断言(可以通过 document.createElement 创建该元素,查看元素的类型)

const handleChange = (event: Event) => {

  // const input = document.createElement('input')

  console.log((event.target as HTMLInputElement).value)

}

</script>

<template>

  <div>

    <h1>我是 App 组件</h1>

    <input type="text" @change="handleChange" />

  </div>

</template>

模板Ref与Typescript

目标:掌握 ref 操作 DOM 时如何配合 Typescript 使用

App.vue

<script setup lang="ts">

import { ref } from 'vue'

const h1Ref = ref(null)

const getElement = () => {

  // 报错,因为初始值是 null,无法从 null 身上获取其他属性。

  console.log(h1.value.innerHTML)

}

// 通过 ref 获取 DOM 时,要通过泛型设置 DOM 类型

const h1Ref = ref<HTMLHeadingElement | null>(null)

const getElement = () => {

  if (h1Ref.value) {

    console.log(h1Ref.value.innerHTML)

  }

}

</script>

<template>

  <div>

    <h1 ref="h1Ref">我是 App 组件</h1>

    <button @click="getH1">获取 h1 元素</button>

  </div>

</template>

可选链操作符和非空断言

目标:掌握 js 中的可选链操作符语法,掌握 ts 中的非空断言的使用语法

访问对象的深层属性时,但是不确定属性是否存在时:

类型守卫:对象中的某个属性存在时,才继续访问它后面的属性

可选链操作符( ?. ):对象中的某个属性存在时,才继续访问它后面的属性

非空断言:如果我们明确的知道对象的属性一定不会为空,那么可以使用非空断言 !

App.vue

<script setup lang="ts">

import { ref } from 'vue'

const h1Ref = ref<null | HTMLHeadingElement>(null)

const changeElement = () => {

  // 方式一:类型守卫(使用if判断)

  if (h1.value) {

    console.log(h1.value.innerHTML)

  }

  // 方式二:可选链操作符(无法做赋值操作)

  console.log(h1.value?.innerHTML)

  // 方式三:非空断言

  // 使用非空断言告诉 ts,h1.value 一定不为空

  // 注意:非空断言一定要确保有该属性才能使用,不然使用非空断言会导致 bug

  console.log(h1.value!.innerHTML)

}

</script>

<template>

  <div>

    <h1>我是 App 组件</h1>

    <button ref="h1Ref" @click="changeElement">修改 h1 元素 innerHTML 内容</button>

  </div>

</template>

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

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

相关文章

21.网络爬虫—js逆向详讲与实战

网络爬虫—js逆向 js逆向JavaScript逆向的详细讲解实战演示有道翻译设置密钥和初始向量对密钥和初始向量进行哈希处理创建AES对象并解密消息移除padding并返回结果 前言&#xff1a; &#x1f3d8;️&#x1f3d8;️个人简介&#xff1a;以山河作礼。 &#x1f396;️&#x1f…

python基于卷积神经网络实现自定义数据集训练与测试

样本取自岩心照片&#xff0c;识别岩心是最基础的地质工作&#xff0c;如果用机器来划分岩心类型则会大大削减工作量。 下面叙述中0指代Anhydrite_rock&#xff08;膏岩&#xff09;&#xff0c;1指代Limestone&#xff08;灰岩&#xff09;&#xff0c;2指代Gray Anhydrite_r…

深度学习-第T6周——好莱坞明星识别

深度学习-第T6周——好莱坞明星识别 深度学习-第T6周——好莱坞明星识别一、前言二、我的环境三、前期工作1、导入数据集2、查看图片数目3、查看数据 四、数据预处理1、 加载数据1、设置图片格式2、划分训练集3、划分验证集4、查看标签 2、数据可视化3、检查数据4、配置数据集 …

Flutter学习之旅 - 页面布局Stack层叠组件

文章目录 StackPositioned定位布局浮动导航(StackPositioned)FlutterMediaQuery获取屏幕宽度和高度StackAlign Stack Stack意思是堆的意思&#xff0c;我们可以用Stack结合Align或者Stack结合Positioned来实现页面的定位布局 属性说明alignment配置所有元素显示位置children子组…

23.Lambda表达式

Lambda表达式 一、Lambda表达式背景 Lambda 表达式(lambda expression)是一个匿名函数&#xff0c;Lambda表达式基于数学中的λ演算得名&#xff0c;直接对应于其中的lambda抽象(lambda abstraction)&#xff0c;是一个匿名函数&#xff0c;即没有函数名的函数。Lambda表达式…

2023-05-05 背包问题

背包问题 1 01背包和完全背包问题 01背包问题 有N件物品和一个容量为V的背包&#xff0c;第i件物品的体积是v[i]、价值是w[i]&#xff0c;每种物品只可以使用一次&#xff0c;求将哪些物品放入背包可以使得价值总和最大。这里的w是weight即权重的意思 这是最基础的背包问题&a…

【飞书ChatGPT机器人】飞书接入ChatGPT,打造智能问答助手

文章目录 前言环境列表视频教程1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 转载自远控源码文章&#xff1a;飞书接入ChatGPT - 将ChatGPT集…

Ubuntu 如何查看 CPU 架构、系统信息、内核版本、版本代号?

Ubuntu 查看 CPU 架构、系统信息、内核版本、版本代号等相关信息有很多方式&#xff0c;本文介绍几种常用的命令。 x86 架构与 ARM 架构的 CPU 架构不同&#xff0c;如果回显为 aarch64 表示为 ARM 架构&#xff0c;如果回显为 x86_64 表示为 x86 架构&#xff0c;参考《CPU 架…

Prometheus快速入门

Prometheus快速入门 环境准备 三台主机&#xff0c;配置好主机名 各自配置好主机名 # hostnamectl set-hostname --static server.cluster.com ... 三台都互相绑定IP与主机名 # vim /etc/hosts 192.168.126.143 server.cluster.com 192.168.126.142 agent.clu…

归并排序(看了就会)

目录 概念1. 基本思想2. 实现逻辑3. 复杂度分析4、代码 概念 归并排序&#xff0c;是创建在归并操作上的一种有效的排序算法。算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用&#xff0c;且各层分治递归可以同时进行。归并排序思路简单&…

智头条|欧盟达成《人工智能法》协议,全球前沿科技齐聚AWE 2023

行业动态 华为云联手多方推进数字化&#xff0c;软通动力深度参与 华为云宣布启动“‘百城万企’应用现代化中国行”&#xff0c;旨在推动应用现代化进程、助力数字中国高质量落地。软通动力是该行动的参与者之一&#xff0c;共同探索符合区域特点、产业趋势、政企现状的数字化…

Python进阶(Linux操作系统)

一&#xff0c;操作系统 1.1&#xff0c;Linux系统基础操作 1.2&#xff0c;linux进程与线程 1.2.1并发&#xff0c;并行 &#xff08;1&#xff09;并发&#xff1a;在一段时间内交替的执行多个任务&#xff1a;对于单核CPU处理多任务&#xff0c;操作系统轮流让让各个任务…

BasicVSR++代码解读(总体介绍)

本文代码主要来自于OpenMMLab提供的MMEditing开源工具箱中的BasicVSR代码。第一部分的解读主要是针对每一个部分是在做什么提供一个解释&#xff0c;便于后续细读每一个块的细节代码。 &#xff08;1&#xff09;导入库     basicvsr_plusplus_net中主要继承了torch,mmcv,m…

信号的产生——线性调频函数

信号的产生——线性调频函数 产生线性调频扫频信号函数chirp的调用格式如下&#xff1a; &#xff08;1&#xff09;y chirp(t,f0, t1,f1) 功能&#xff1a;产生一个线性&#xff08;频率随时间线性变化&#xff09;信号&#xff0c;其时间轴设置由数组t定义。时刻0的瞬间频…

SpringBoot的配置文件、日志文件

一、配置文件&#xff08; .properties、.yml&#xff09; 1、.properties 配置文件 1.1、格式 1.2、基本语法 1.2.1、如&#xff1a;一般配置&#xff08;以键值的形式配置的&#xff0c;key 和 value 之间是以“”连接的。&#xff09; 1.2.2、如&#xff1a;自定义配置&a…

tcc-transaction 源码分析

tcc介绍 tcc介绍查看我之前的文章&#xff1a; https://caicongyang.blog.csdn.net/article/details/119721282?spm1001.2014.3001.5502 tcc-transaction 介绍&#xff1a; http://mengyun.org/zh-cn/index.html 本文基于2.x 最新版本:https://github.com/changmingxie/tcc…

以京东为例,分析优惠价格叠加规则

一、平行优惠计算原则 1、什么是“平行式门槛计算规则”&#xff1f; 平行式门槛计算规则&#xff0c;即每一层级优惠都直接根据商品的单品基准价来计算是否符合门槛&#xff0c;店铺/平台促销、优惠券类优惠之间是并列关系&#xff0c;只要单品基准价或单品基准价总和&#x…

c++(类和对象中)

【本节目标】 1. 类的6个默认成员函数 2. 构造函数 3. 析构函数 4. 拷贝构造函数 5. 赋值运算符重载 6. const成员函数 7. 取地址及const取地址操作符重载 目录 1、类的6个默认成员函数 2、构造函数 2.1概念 2.2特性 3.析构函数 3.1概念 3.2特性 4.拷贝构造函数…

Kafka生产者

一、生产者发送流程 在消息发送的过程中&#xff0c;涉及到了两个线程——main 线程和 Sender 线程。在 main 线程中创建了一个双端队列 RecordAccumulator。main 线程将消息发送给 RecordAccumulator&#xff0c;Sender 线程不断从 RecordAccumulator 中拉取消息发送到 Kafka …

网络应用基础 ——(2023新星计划文章二)

一&#xff0c;TCP/UDP报头 1.1TCP报文头部详解 Source port:源端口号与Destination port目标端口号&#xff1a; 在TCP&#xff08;传输控制协议&#xff09;协议中&#xff0c;源端口和目标端口字段用于标识通信会话的端点。 &#xff08;1&#xff09;源端口是一个16位字段…