VUE3 + TS学习记录

TS核心

 联合类型   (string | number)[] 

let arr: (string | number)[] = ['a',100]

 类型别名(type关键词)  

  • type 类型别名 = 具体类型 基本语法
  • 定义类型别名,遵循大驼峰命名规范,类似于变量
  • 使用类型别名,与类型注解的写法一样即可
  • type 有 = 号,interface无 = 号
type ItemType = (string | number)[]

let arr: ItemType = ['a',100]

let arr2: ItemType = [100,200,'a','b']

// 函数复用并同时指定
type AddFn = (a:number ,b:number) => number
const aFn: AddFn = (num1,num2) => {
    return num1+num2
}
aFn(1,2)


type Person = {
    name: string
    age: number
    gender?: string
}

let p: Person = {
    name: 'aa',
    age: 10
}

// 交叉类型(&)
type PersonA = Person & {
    id: number
}

let p2: PersonA = {
    name: 'aa',
    age: 10,
    id: 1
}

继承: 交叉类型(&)

        

  • 使用 & 可以合并连接的对象类型,也叫:交叉类型
// 使用 type 来定义 Point2D 和 Point3D
type Point2D = {
  x: number
  y: number
};
type Point3D = {
  x: number
  y: number
  z: number
};


// 使用 交叉类型 来实现接口继承的功能:
// 使用 交叉类型 后,Point3D === { x: number; y: number; z: number }
type Point3D = Point2D & {
  z: number
};

let o: Point3D = {
  x: 1,
  y: 2,
  z: 3,
};

接口(interface)

  • interface  接口名称,和类型别名的意思一样。
  • 指定 接口名称 作为变量的类型使用。
  • 接口的每一行只能有 一个 属性或方法,每一行不需要加分号。
  • type 有 = 号interface无 = 号
interface Person {
    name: string
    age: number
    gender?: string
}

const p: Person = {
    name: 'gao',
    age: 18
}


let list: Person[] = [
    {
        name: 'gao',
        age: 18,
    }
]


// 多层嵌套结构,定义先内层在外层
{
      code: 200,
      msg: '成功',
      data: {
        num: 1,
        a: 'sss'
      }
 }

interface Data {
    num: number
    a: 'string'
    ad?: 'string'
}
interface ResData {
    code: number
    msg: string
    data: Data
}

继承(extends)

使用 extends 实现接口继承,达到类型复用
// 有两个接口,有相同的属性或者函数
interface Point2D {
  x: number;
  y: number;
}

interface Point3D {
  x: number;
  y: number;
  z: number;
}


// 相同的属性或展示可以抽离出来,然后使用 extends 实现继承复用
interface Point2D {
  x: number;
  y: number;
}
// 继承 Point2D
interface Point3D extends Point2D {
  z: number;
}
// 继承后 Point3D 的结构:{ x: number; y: number; z: number }

字面量类型(可选范围)

// 场景1
type Gender = '男' | '女'
let gender: Gender = '男'

// 场景2
type Res = {
    code: 200 | 400 | 500
    msg: string
}
let res: Res = {
    code: 200,
    msg: 'success'
}

let count: 100
count = 100
count = 200 // error

let name: 'gao'

泛型(Generics) <>不预先指定具体类型,使用的时候再来指定

// 场景
{
      code: 200,
      msg: '成功',
      data: {
        num: 1,
        a: 'sss'
      }
 }

{
      code: 200,
      msg: '成功',
      data: {
        id: 1,
        content: '内容'
      }
 }


type Res<T> = {
    code: number
    msg: string
    data: T
}

type Data1 = {
    num: number
    a: string
}

type Data2 = {
    id: number
    content: string
}

let res: Res<Data1> = {
    code: 200,
    msg: 'success',
    data: {
        num: 1,
        a: 'sss'
    }
}
let res2: Res<Data2> = {
    code: 200,
    msg: 'success',
    data: {
        id: 1,
        content: '内容'
    }
}

泛型函数

// 函数的参数是什么类型,返回值就是什么类型
function getId<T>(id: T): T {
  return id
}

let id1 = getId<number>(1)
let id2 = getId('2')
// TS会进行类型推断,参数的类型作为泛型的类型 getId<string>('2')

枚举

enum Direction {
    Up,
    Down,
    Left,
    Right,
}
// Up的值为 0, Down的值为 1等等

enum Direction {
    Up = 1,
    Down,
    Left,
    Right
}

如上,我们定义了一个数字枚举, Up使用初始化为 1。 其余的成员会从 1开始自动增长。 换句话说, Direction.Up的值为 1, Down为 2, Left为 3, Right为 4

// 字符串枚举
enum Direction {
    Up = "UP",
    Down = "DOWN",
    Left = "LEFT",
    Right = "RIGHT",
}

无返回值 void

const say = (): void => {
  console.log('hi');
};

any

any 类型的作用是逃避 TS 的类型检查,不会有任何错误,也不会有代码提示,TS会忽略类型检查

let obj: any = { age: 18 }
obj.bar = 100
obj()
const n: number = obj

类型注解

let msg: string
msg = 'this is message'

let count: number
let isBoolean: boolean

let arr: number[] ====>   // 泛型写法: let arr: Array<number> = [1,2,3]
arr = [1,2,3]

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

// 联合类型
let arr3: (string | number)[] = ['a', 100]

// 函数声明
function add(num1: number, num2: number): number {
  return num1 + num2;
}

// 箭头函数
const add = (num1: number, num2: number): number => {
  return num1 + num2;
};

// 复用并同时指定
type AddFn = (num1: number, num2: number) => number;

const add: AddFn = (num1, num2) => {
  return num1 + num2;
};

类型断言(as)

const aLink = document.getElementById('link') as HTMLAnchorElement
aLink.href = ''

三斜线指令

三斜线指令可放在包含它的文件的最顶端。 一个三斜线指令的前面只能出现单行或多行注释,这包括其它的三斜线指令。 如果它们出现在一个语句或声明之后,那么它们会被当做普通的单行注释,并且不具有特殊的涵义。

/// <reference path="..." />

/// <reference path="..." />指令是三斜线指令中最常见的一种。 它用于声明文件间的 依赖。

三斜线引用告诉编译器在编译过程中要引入的额外的文件

Omit和Pick

Omit 是从对象中排除一些属性

用法: Omit<对象,属性|属性>

type Person = {
    name: string
    age: number
    gender: 0|1
    address: string
    tel: number
}

type OmitPerson = Omit<Person, 'age'|'gender'>

// {
//    age: number
//    gender: 0|1
// }


type OmitUser = Omit<Person, 'age'>
type UserInfo = OmitUser & {
    id: number
    token: string
}

// {
//    name: string
//    gender: 0|1
//    address: string
//    tel: number
//    id: number
//    token: string
// }

Pick 是从对象中摘取一些属性

用法:Pick<对象, 属性|属性>

type Person = {
    name: string
    age: number
    gender: 0|1
    address: string
    tel: number
}

type PickPerson = Pick<Person, 'name'|'age'>

// { 
//   name: string
//   age: number
// }

V3中使用Ts

ref函数标注类型和泛型的使用

函数标注、模板引用标注

// 元素事件标注
const inputChange = (e: Event) => {
  console.log((e.target as HTMLInputElement).value);
}

// 模板引用标注类型
const inputRef = ref<HTMLInputElement | null>(null)
function iptFocus() {
  inputRef.value?.focus()
}

props标注类型

type Props = {
  color: string // 必传参数
  size?: string
}
const props = defineProps<Props>()

默认值( withDefaults(defineProps<Props>(), {默认值}))


type Props = {
  color: string
  size?: string
}

const props = withDefaults(defineProps<Props>(), {
  size: 'middle'
})

emits标注类型

约束事件名称 + 参数类型


type Emits = {
  (e: 'get-msg', msg: string): void
}

const emit = defineEmits<Emits>()

function clickHandler() {
  emit('get-msg','this is value')
}


// 数组类型
type ListItem = {
    id: number
    name: string
}

type Emits = {
  (e: 'get-list', list: ListItem[]): void
}

const emit = defineEmits<Emits>()

function clickHandler() {
  emit('get-list', [{ id: 1, name: 'gao' }] )
}

类型声明文件 d.ts

为js模块提供类型信息支持。

TS会自动导入模块对应的d.ts文件,以提供类型提示

 有些库本身不是ts编写的,无法直接生成配套的d.ts文件,可以使用DefinitelyTyped提供类型声明文件

yarn add @types/jquery -D

axios

axios要根据后端返回值写标注类型,泛型放在axios.request

type DataItem = {
  article_id: number
  articel_name: string
}

type ArticleResData = {
  code: number,
  data: DataItem[],
  msg: string
}


async function getList() {
  const res = await axios.request<ArticleResData>({
    url: '',
    method: 'GET',
    params: {
      id: 1001
    }
  })
}


// 抽出公用部分
type CommonData<T> = {
  code: number,
  data: T,
  msg: string
}

type ChannelItem = {
    id: number
    name: string
}
type ARes = CommonData<{
    channels: ChannelItem[]
}>

type ArtItem = {
    pic_id: number
    url: string
}
type BRes = CommonData<{
    arts: ArtItem[]
}>

Pinia

appInfo.ts

import { defineStore } from "pinia";
import { computed, ref } from "vue";

export const useInfoStore = defineStore('info', () => {

  // state
  const count = ref(0)

  // function
  function changeCount() {
    count.value++
  }

  // getter
  const doubleCount = computed(() => {
    count.value * 2
  })

  // 定义类型
  type ChannelItem = {
    id: number
    name: string
  }
  type ResData = {
    data: {
      channels: ChannelItem[]
    }
    message: string
  }
  // action
  const list = ref<ChannelItem[]>([]) // list = [{id: 1001,name: '短袖'}]
  async function getList() {
    // const res = await xxx()
    // list.value = res.data
  }

  return { count, doubleCount, list, getList, changeCount, }
})

使用pinia

storeToRefs:解构数据后,还保持数据(state+getter)的响应式

<script setup>
import { storeToRefs } from "pinia";
import { useInfoStore } from "@/store/app.js";

const store = useInfoStore();
// storeToRefs:解构数据后,还保持数据(state+getter)的响应式
let { count} = storeToRefs(store);


// 方法就是直接解构
const { changeCount } = store 

</script>

pinia持久化存储

pnpm add pinia-plugin-persistedstate

用法: 

// store>index.ts

import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'

export * from './modules/userInfo'

// 创建pinia实例
const pinia = createPinia()
// 使用pinia插件
pinia.use(persist)
// 导出pinia实例,给main使用
export default pinia




// main.ts

import { createApp } from 'vue'

import App from './App.vue'
import pinia from './stores'
import router from './router'

import '@/styles/main.scss'

// toast
import 'vant/es/toast/style';
// Dialog
import 'vant/es/dialog/style';
// Notify
import 'vant/es/notify/style';
// ImagePreview
import 'vant/es/image-preview/style';


async function setupApp() {
  // 创建vue实例
  const app = createApp(App)

  // 注册模块Pinia
  await app.use(pinia)

  // 注册模块 Vue-router
  await app.use(router)

  // 挂载
  app.mount('#app')
}
setupApp()

pnpm

  • 29
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值