一,前言
继续学习
二,TS接口泛型自定义类型
1.接口
TypeScript 接口(Interface)是一种定义对象形状的强大工具,它可以描述对象必须包含的属性、方法和它们的类型。接口不会被编译成 JavaScript 代码,仅在编译阶段用于类型检查。
基本语法与用法
接口使用 interface
关键字定义,下面是一些常见用法:
// 定义基本接口
interface User {
name: string;
age: number;
//“?” 表明该属性是可选的,其数据类型为布尔型(即值只能是 true 或 false)。“readonly id: string;” 表示定义一个名为 “id” 的属性,“readonly” 关键字意味着这个属性一旦被赋值就不能再被修改
isAdmin?: boolean; // 可选属性
readonly id: string; // 只读属性
greet: (message: string) => void; // 方法
}
// 使用接口
const user: User = {
name: "张三",
age: 30,
id: "user123",
greet: (message) => console.log(`${message}, ${this.name}`)
};
// 接口继承
interface AdminUser extends User {
role: string;
}
// 函数接口
interface Calculator {
(a: number, b: number): number;
}
const add: Calculator = (a, b) => a + b;
// 可索引接口
interface StringArray {
[index: number]: string;
}
const names: StringArray = ["Alice", "Bob"];
高级特性
接口还支持更复杂的类型定义:
// 混合类型接口(对象 + 函数)
interface Counter {
(): void; // 函数签名
count: number; // 属性
}
function createCounter(): Counter {
const counter = () => counter.count++;
counter.count = 0;
return counter;
}
// 接口合并(同名接口会自动合并)
interface Box {
height: number;
}
interface Box {
width: number;
}
const box: Box = { height: 10, width: 20 };
最佳实践
- 使用接口定义对象形状,特别是在大型项目中
- 使用类型别名处理联合类型、交叉类型等复杂类型
- 保持接口名称简洁明了,通常使用名词或形容词 + 名词
- 为可选属性添加
?
标记,为只读属性添加readonly
标记
接口是 TypeScript 类型系统的核心组成部分,合理使用可以显著提高代码的可读性和可维护性。
2.泛型
泛型是 TypeScript 中一个强大的特性,它允许我们创建可重用的组件,同时保持类型安全。泛型让我们可以在定义函数、接口或类时不预先指定具体类型,而是在使用时再确定类型。
基本泛型函数:
// 泛型函数示例
function identity<T>(arg: T): T {
return arg;
}
// 使用泛型函数
const output1 = identity<string>("myString"); // 显式指定类型
const output2 = identity(100); // 类型推断为 number
泛型接口:
// 泛型接口
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
const myIdentity: GenericIdentityFn<number> = identity;
泛型类:
// 泛型类
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
const myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = (x, y) => x + y;
3,自定义类型
自定义类型允许我们创建复杂的、特定用途的类型定义,提高代码的可读性和类型安全性。
类型别名(Type Aliases):
// 基本类型别名
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
// 复杂类型别名
type UserInfo = {
name: string;
age: number;
address?: string;
};
// 泛型类型别名
type Container<T> = { value: T };
交叉类型(Intersection Types):
// 交叉类型
interface Colorful {
color: string;
}
interface Circle {
radius: number;
}
type ColorfulCircle = Colorful & Circle;
const cc: ColorfulCircle = {
color: "red",
radius: 10
};
联合类型
// 联合类型
type StringOrNumber = string | number;
type Text = string | { text: string };
// 字面量类型
type Easing = "ease-in" | "ease-out" | "ease-in-out";
**条件类型
// 条件类型
type MessageOf<T> = T extends { message: unknown } ? T["message"] : never;
interface Email {
message: string;
}
type EmailMessageContents = MessageOf<Email>; // string
映射类型
// 映射类型
interface User {
name: string;
age: number;
email: string;
}
// 创建只读版本
type ReadonlyUser = {
readonly [P in keyof User]: User[P];
};
// 创建可选版本
type PartialUser = {
[P in keyof User]?: User[P];
};
三,v-for指令
v-for
是 Vue.js 中用于循环渲染列表的指令,它允许你基于数组或对象的数据来动态生成 DOM 元素。
基本用法
v-for
指令的基本语法是 item in items
,其中 items
是源数据数组,而 item
是当前被迭代的数组元素的别名。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Vue v-for 简单示例</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<style>
body { font-family: Arial, sans-serif; }
.example { margin-bottom: 30px; padding: 15px; border: 1px solid #eee; }
ul { list-style-type: none; padding: 0; }
li { margin: 5px 0; }
</style>
</head>
<body>
<div id="app">
<!-- 示例1:循环数组 -->
<div class="example">
<h3>1. 循环数组</h3>
<ul>
<li v-for="(item, index) in fruits" :key="index">
{{ index + 1 }}. {{ item }}
</li>
</ul>
</div>
<!-- 示例2:循环对象 -->
<div class="example">
<h3>2. 循环对象</h3>
<ul>
<li v-for="(value, key) in user" :key="key">
{{ key }}: {{ value }}
</li>
</ul>
</div>
<!-- 示例3:循环数字 -->
<div class="example">
<h3>3. 循环数字</h3>
<p>前 {{ count }} 个数字的平方:</p>
<ul>
<li v-for="n in count" :key="n">
{{ n }} × {{ n }} = {{ n * n }}
</li>
</ul>
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
fruits: ['苹果', '香蕉', '橙子', '草莓'],
user: {
name: '张三',
age: 28,
email: 'zhangsan@example.com'
},
count: 5
}
})
</script>
</body>
</html>
- key 的重要性:
- 为每个 v-for 项提供唯一的 key 是最佳实践,它帮助 Vue 跟踪节点的身份,从而高效地更新 DOM。
- 避免使用索引作为 key,特别是当列表可能会重新排序或过滤时,这可能导致性能问题或错误的更新。
- 响应式更新:
- Vue 能够检测到数组的变更方法(如 push、pop、splice 等)并触发相应的 DOM 更新。
- 直接修改数组索引或长度不会触发响应式更新,应使用 Vue 提供的方法。
- 过滤和排序:
- 当需要显示过滤或排序后的结果时,应使用计算属性或方法,而不是在 v-for 中直接操作。
四,props
props
是 Vue 组件中用于从父组件向子组件传递数据的机制。它允许你创建可复用的组件,同时保持数据的单向流动。
index.ts
// 定义一个接口,用于限制person对象的具体属性
export interface PersonInter
{
name: string;
age: number;
sex: string;
}
// 一个自定义类型
export type Persons = PersonInter[]
App.vue
<template>
<person a="hh":list="personlist"/>
</template>
<script lang="ts" setup name="App">
import person from './components/person.vue';
import { reactive } from 'vue';
import { type Persons} from './types';
let personlist = reactive<Persons>([
{
name:'张三',
age:18,
sex:'男',
},
{
name:'李四',
age:19,
sex:'男',
},
{
name:'王五',
age:20,
sex:'男'
},
])
</script>
person.vue
<template>
<div class="person">
<h2>
{{a}}
</h2>
<ul>
<li v-for="p in list" :key="p.id">
{{p.name}} {{p.age}}
</li>
</ul>
</div>
</template>
<script lang="ts" setup name="Person">
import { defineProps } from 'vue';
// // 接收a参数和list
defineProps(['a','list'])
// // 接收a参数,同时将props保存起来
// let x = defineProps(['a'])
// console.log(x.a)
</script>
<style>
</style>
大概就是这样,反正就是从父组件那里搞点数据,还有很多别的用法遇到了再说。