【菜狗学前端】 初探TS(结合在vue3中的使用)

佛系菜狗 2024-08-05 15:33:01 阅读 69

TypeScript是拥有类型的JavaScript超集,它可以编译成普通、干净、完整的JavaScript代码。我们可以将TypeScript理解成加强版的JavaScript。

简单来说:Ts是带类型语法的Js; Ts是Js的超集

TS官方网站:https://www.typescriptlang.org/

TS中文官网:https://www.tslang.cn/

一、基础语法

js已有类型:

        基本类型: number, string, boolean, null, undefined, symbol,BigInt

        引用数据类型:对象、数组、函数

ts新增类型:

        联合类型、类型别名、接口、元祖、字面量类型、枚举、void、any、泛型等

(一) 原始类型

1.简单类型 :xx

<code>let age: number = 18;

let uname: string = "zhangsan";

let flag: boolean = false;

// null和und类型用的比较少

let nullValue: null = null;

let undefinedValue: undefined = undefined;

PS:其实最后.ts转为.js文件时void仍会变为undefined,TS中加上void一般只是为了将函数返回值和其他区分出来。

2.引用类型 :xx[]

a.数组

let arr1 = ["a", "b", "c"]

let arr3: number[] = [1, 2, 3]

let arr2: string[] = ["a", "b", "c"]

console.log(arr1, arr2, arr3);

let arr4: Array<string> = ["ok", "hello"]

console.log(arr4);

思考:数组中是可以存放多种数据类型

        联合类型:|(竖线)在TS中叫做联合类型

        即:由两个或多个其他类型组成的类型,表示可以是这些类型中的任意一种

b.函数

// 函数 给参数和返回值 指定类型

// 函数声明(具名函数)

function add(a: number, b: number): number {

    return a + b

}

console.log(add(1, 2));

// 函数表达式(匿名函数)

let add2 = (a: number, b: number): number => {

    return a + b

}

console.log(add2(1, 2));

// 箭头函数写法

type AddFn = (a: number, b: number) => number

// 通过类似箭头函数形式的语法为函数添加类型,只适用于函数表达式

let add3: AddFn = (a, b) => {

    return a + b

}

console.log(add3(3, 3));

可选参数?

使用 ? 将参数标记为可选

const fn = (n?: number) => {

}

fn()

fn(1)


函数返回值:

在js中默认返回值是und,在ts中默认返回的是void

如果指定返回值类型是 undefined 那返回值一定是 undefined

// void和undfined类型

// 如果函数没有返回值,定义函数类型时返回值的类型为void

const say = () => {

    // console.log('hello ts~');

}

console.log(say());

console.log(typeof say());

const say2 = (): void => {

    // console.log('hello ts~');

}

console.log(say2());

console.log(typeof say2());

// 区分:在js中默认返回值是und,在ts中默认返回的是void

// 如果指定返回值类型是 undefined 那返回值一定是 undefined

const say3 = (): undefined => {

    // console.log('hello ts~');

}

console.log(say3());

console.log(typeof say3());

c.对象

// 空对象

let obj1 = {}

let obj2: {} = {}

// 指定对象里面的属性和方法

// let obj4: { name: string, say(): void } = {

let obj4: { name: string; say(): void } = {

    name: "wc",    // 对象里面写方法的两种写法    // say():void    say: () => void

}

// 竖着写 可以换行

let obj5: {

    // name: string,

    name: string;

    say(): void

} = {

    name: "wc",

    say() { }

}

(二) 类型别名 type

给某个指定类型起别名

定义类型别名,遵循大驼峰命名,类似于变量

        什么时候是用类名别名?

        当同一类型(引用)被多次使用,可以通过类型别名简化

// 语法:type 类型别名=具体类型

type A = (string | number)[]

let arr9: A

arr9 = [1, "a", 3]

交叉类型 &

// type  交叉类型

type APoint2D = {

    x: number,

    y: number

}

type APoint3D = APoint2D & {

    z: number

}

let o: APoint3D = {

    x: 1,

    y: 2,

    z: 3

}

(三) 接口 interface (可继承extends)

interface 后面跟的是接口名称

注意:接口的每一行只能有一个属性或者一个方法 每一行不需要加分号

interface Person {

    name: string

    age: number

    say: () => void

}

let p: Person = {

    name: "wangcai",

    age: 18,

    say() { }

}

console.log(p);

// 接口是可继承的

// 2D坐标

interface Point2D {

    x: number

    y: number

}

let p2: Point2D = {

    x: 1,

    y: 2

}

console.log(p2);

// 如何实现继承?

// 使用extends实现接口继承,达到类型复用

// 继承后 接口A 拥有了接口B的所有属性和函数的类型声明 interface Point3D extends Point2D {    z: number}

let p3: Point3D = {

    x: 1,

    y: 2,

    z: 3

}

(四)interface和type的区别

1.type是起别名,interface 是自己发明类型 自定义类型

 

// 会报错

// type APerson = {

//     name:string

// }

// type APerson = {

//     age:number

// }

interface Person1 {

    name1: string

};

interface Person1 {

    age1: number

};

// 类型合并

const c1: Person1 = {

    name1: "wc",

    age1: 18

}

2.type不可以重复定义,interface可以重复定义会合并

3.type支持对象类型和其他类型,interface只支持对象类型

4.type复用:交叉类型 &,interface复用:可以继承 extends

二、ts在vue3中的使用

(一)ref和ts

// 手动指定类型

const count =ref<number>(0)

<template>

    <div>{ { count }}</div>

    <ul>

      <li v-for="item in list" :key="item.id">code>

        { { item.name }}

      </li>

    </ul>

</template>

<script setup lang="ts">code>

import { ref, reactive } from "vue"

// 手动指定类型const count =ref<number>(0)

// 自动类型

const count1=ref(0)

type ToDoItem={

  id:number;

  name:string;

  done:boolean

}

// [{},{},{}]

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

setTimeout(()=>{

  list.value=[

  { id: 100, name: "吃饭", done: false },

  { id: 101, name: "睡觉", done: false },

  ]

},1000)

</script>

(二)reactive和ts

type Book={

title:string;

year?:number

}

const book:Book=reactive({

title:"ts语法基础"

})

<template>

    { { book.title }} -- { { book.year }}

</template>

<script setup lang="ts">code>

import { ref, reactive } from "vue"

// 1.手动指定类型

type Book={

  title:string;

  year?:number

}const book:Book=reactive({

  title:"ts语法基础"

})

book.year=2023

// 2.自动类型推导

const Book=reactive({title:"ts语法基础2"})

</script>

(三)computed和ts

const doubleCountB = computed<string(() => (count.value * 2).toFixed(2))

<template>

  { { count }} -- { { doubleCount }} -- { { doubleCountB }}

  { { typeof count }} -- { { typeof doubleCount }} -- { { typeof doubleCountB }}

</template>

<script setup lang="ts">code>

import { ref, computed } from "vue"

const count = ref(205)

// 1.自动类型推导

// toFixed(2)保留2位小数,且返回值类型为string

const doubleCount = computed(() => (count.value * 2).toFixed(2))

// 2.指定计算属性的类型

const doubleCountB = computed<string>(() => (count.value * 2).toFixed(2))

</script>

(四)defineprops和ts(父传子)

defineProps<{

money:number;

car?:string

}>()

Child.vue

<template>

    <div class="">code>

      <p>{ { money }}</p>

      <p>{ { car }}</p>

    </div>

</template>

<script setup lang="ts">code>

// vue3基本写法

// defineProps({

//     money:{

//         type:Number,

//         required:true

//     }

// })

// ts基本语法

// defineProps<{

//     money:number;

//     car?:string

// }>()

// ts+有默认值的写法

withDefaults(

    defineProps<{

        money:number;

        car?:string

    }>(),{

        money:666,

        car:"xiaomi"

    }

)

</script>

App.vue

<template>

 <div>

  <!-- 父传子 -->

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

 </div>

</template>

<script setup lang="ts">code>

import { ref} from "vue"

import Child from "./components/Child.vue"

const money=ref(666)

const car=ref('大众')

</script>

(五)defineEmits和ts(子传父)

const emit =defineEmits<{

(e:"changeMoney",money:number):void;

(e:"changeCar",car:string):void;

}>()

Child.vue

<template>

    <p>{ { money }}</p>

    <button @click="emit('changeMoney', 800)">改money</button>code>

    <p>{ { car }}</p>

    <button @click="emit('changeCar', '宝马')">改car</button>code>

</template>

<script setup lang="ts">code>

// vue3基本写法

// const emit = defineEmits(["changeMoney", "changeCar"])

// ts写法

defineProps<{

  money: number;

  car?: string;

}>()

const emit =defineEmits<{

    (e:"changeMoney",money:number):void;

    (e:"changeCar",car:string):void;

}>()

</script>

App.vue

<template>

 <!-- 子传父 -->

 <Child

 :money="money"code>

 :car="car"code>

 @change-money="money=$event"code>

 @change-car="car=$event"code>

 ></Child>

</template>

<script setup lang="ts">code>

import { ref} from "vue"

import Child from "./components/Child.vue"

const money=ref(666)

const car=ref('大众')

</script>

(六)事件处理和ts :Event

as 断言​​​​​​​

e:Event

<template>

    <input type="text" @change="handleChange" value="hi">code>

</template>

<script setup lang="ts">code>

// 不处理类型

// const handleChange=(e)=>{

//     console.log(e.target.value)

// }

const handleChange=(e:Event)=>{

    // as 断言

    // e.target 事件源

    console.log((e.target as HTMLInputElement).value);

}

</script>

(七)ref写在标签上获取 :HTMLInputElement

const input = ref<HTMLInputElement | null(null)

<template>

    <div>

        <input type="text" ref="input">code>

    </div>

</template>

<script setup lang="ts">code>

import { onMounted, ref } from 'vue'

const input = ref<HTMLInputElement | null>(null)

// 页面加载完毕调用钩子函数

onMounted(()=>{

    input.value?.focus()

})

</script>

(八)非空断言 !

// ! 非空断言(方法一)

input.value!.value = "456" //可以赋值

// 类型守卫(方法二)

if (input.value) {

input.value.value = "789" //可以赋值

}

<template>

    <div>

        <input type="text" ref="input" value="123">code>

    </div>

</template>

<script setup lang="ts">code>

import { onMounted, ref } from 'vue'

const input = ref<HTMLInputElement | null>(null)

// 页面加载完毕调用钩子函数

onMounted(() => {

    // 自动获取焦点

    input.value?.focus()

    // 使用ES6 输入框没有获取到,对于可能出现null,

    console.log(input.value?.value);

    // ?可选参数 可选链  报错 因为不能赋值

    // input.value?.value = "456"

    // ! 非空断言(方法一)

    input.value!.value = "456" //可以赋值

    // 类型守卫(方法二)

    if (input.value) {

        input.value.value = "789" //可以赋值

    }

})

</script>



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。