Yang的Vue3.2+TS入门

1,062 阅读6分钟

前言:

记录Yang的Vue3.2+vite+TS入门学习总结,可供萌新朋友们参考
该笔记分为Vue3.2TS入门两个部分
大佬们推荐的实用工具:
✅脚手架:vite
✅路由:vue-router4
✅状态管理:pinia
✅Hooks库:vueuse
✅自动导入插件(懒人必备):unplugin-vue-components、unplugin-auto-import/vite

Vue3.2

思考:为什么特意说时3.2而不是3.x呢?
答:因为3.2版本出现了人见人爱的setup语法糖

-Vue3组合式API与Vue2配置项的差别

下面是Vue3.2组合式api的一个小demo:

<script setup >
import {ref,reactive,onMounted,defineProps,defineEmits} from 'vue'
let my_name = ref('Yang')
let person= reactive({
   name:'Yang'
   age:18
   pet:{
   pet_name:'小白'
   pet_age:3
   }
   playBasketBall(){
   console.log('洋仔正在打篮球')
   }
})
function doSomething(someone,dosomething){
 console.log(`${someone}正在${dosomething}!`)
}
onMounted(()=>{
console.log('挂载成功!')
})
//父子传参
const props = defineProps({
  foo: String
})
const emit = defineEmits(['change', 'delete'])
-----------------------------------------------------------
console.log(my_name.value)
//输出结果:Yang
<script>

demo出现的几个基本API:


ref---使基本数据类型变为响应式,但在js中使用时要得到数据必须.value,vue实例中不用.value
reactive---使复杂数据类型变为响应式
moMounted---生命周期钩子
defineProps,defineEmits---父子传参
还有未出现的很多基本api如computed,watch等等,这些api与Vue2中的配置项用法基本相同

-Vue3.2的优点:

与Vue2相比:

1.组合式api比起配置项更适合代码量庞大的项目,将实现一种功能的代码放在一起,而不是分别放在 data,methods,mounted等不同的配置项中
2.组合式api更适合自定义Hooks
3.全面拥抱TS
4.支持tsx//虽然我还不会 与Vue3.0相比:


setup语法糖,无需一个个return//第一次看到Vue3.0就是被繁琐的return劝退了

Typescript入门

TS显式类型-限制类型

const a: number = 1
const b: string ='woaini'
const c: boolean = true
------------------------------------------------
const d = [1,'woaini',true]//任意元素的数组
const e: number[] =[1,2,3]//限制元素类型的数组
const f: Array<number>=[3,4,5]//限制元素类型的数组
-----------------------------------------------------
  function test (x: number,y?: string)  //?:表示可传参,也可不传
{
  if(y)
  {
    consolie.log(y)
  }
  或者
  console.log(y?.join())
  //不确定是否存在y所以必须这样使用
}

联合类型和类型别名和接口

1.联合类型

number | string //称为联合类型
#### 2.类型别名

2.类型别名

type Userid = number | string   //此时userId变成一个新类型,类型别名一般大写
function test (x: UserId)

3.接口

interface Point{
  x: string;
  y: strng	;
}
function test (x: Point)

--接口和类型别名的区别:

1.类型别名定义必须有'='等号,接口不需要
2.接口是可扩展的,类型别名不能重复定义

interface Point{
  x: string
}
interface Point{
  y: string
}
//等价于
interface Point{
  x: string
  y: string
}
而
type Point =number
type Point =string
报错,不能出现两个Point

3.接口可以通过extends继承新的成员,而类型别名不可以
4.接口算是一种特殊的抽象类,用来规范类的格式-详情见类

类型断言和文本类型

类型断言:

将不确定的类型在编译时指定为具体的类型

类型断言的两种方式

1.as:(主要使用as,因为jsx支持as)

 const a: any='hello' as string

2.尖括号:

const <string>a: any='hello'

文本类型:
将类型限制成更具体的string,number,boolean中的值

function test (a: 'get' | 'post' |)//只能传入post和get字符串
const a ={
 testoption: 'get'//现在是string类型
}
function test (a.testoption as 'get')//更具体

类型缩小:

function test (a: array | string | null)
{
  if (typeof a=='object'/'string'/'number'){  }  
}

:typeof array和null都是'object'

类:

三种访问权限:public private protected且以修饰符的形式使用

与c++不同的是,TS中默认权限为public

class Animal{
  name: string
	age: number
  constructor(name: string,age: number){
    this.name=name
    this.age=age
  }
}
class Cat extends Animal
{
  kind: string
  constructor(name: string,age: number,kind: string){
    super(name,age)//super关键字-指向父类实例的指针,这里调用父类构造函数
    this.kind=kind
  }
}
-------------------------------------------------------
let cat = new Cat('咪咪'3'布偶')

重点:

  • 构造函数-constructor

  • 继承-extends

  • 子类中重写父类的属性或方法调用时优先调用子类的,此时想要使用父类的属性或方法使用super关键字(一个指向父类实例的指针)

  • 抽象类:无法实例化对象,专门用来被继承的类-abstract关键字

  • 抽象函数:abstract关键字,不在子类中书写该函数则会报错,专门用来提示

abstract class Animal{
  name: string
	age: number
  constructor(name: string,age: number){
    this.name=name
    this.age=age
  }
  abstract sayHello(){
  }
}
  • 在类中实现接口:接口算是一种特殊的抽象类,用来规范类的格式
interface animal{
  name: stringS
	age: number
  sayHello()   //不写函数体,也不用写构造函数
}
class Animal implements animal{
  name: string
	age: number
  constructor(name: string,age: number){
    this.name=name
    this.age=age
  }
	sayHello(){
    console.log('hello')
  }
}
  • 几个重要的修饰符:public private protected static abstract set和get
  • 属性存取器:getter和setter 调用时不用调函数,有语法糖
class dog{
private name: string
private age: number
  constuctor(name: string,age: number){
    this.name=name
    this.age=age
  }
  set name(name: string)
  {
    this.name=name
  }
  get name(){
  return this.name
  }
}
------------------------------------------------
let dog1 = new dog('旺财',3)
console.log(dog1.name)//getter语法糖,不需要调用get方法
dog1.name='大黄' //setter语法糖,不需要调用set方法

泛型:

普通的泛型我把它理解为模板类型,普通的泛型很简单,这里不过多赘述了
包括:泛型函数,泛型接口,泛型类
直到出现下面这个东西,我懵了

发现b站和掘金作者有这种用法,但是没有具体说明,官方文档也没有

探索未知的道路

1.21---------------------------------------------------------------------------------------------------------------

今天再次观摩vue3文档时发现了答案,以下摘自vue3官网

仅限类型的 props/emit 声明:

props 和 emits 都可以使用传递字面量类型的纯类型语法做为参数给 defineProps 和 defineEmits 来声明:

const props = defineProps<{
  foo: string
  bar?: number
}>()

const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()
  • defineProps 或 defineEmits 只能是要么使用运行时声明,要么使用类型声明。同时使用两种声明方式会导致编译报错。
  • 使用类型声明的时候,静态分析会自动生成等效的运行时声明,以消除双重声明的需要并仍然确保正确的运行时行为。
    • 在开发环境下,编译器会试着从类型来推断对应的运行时验证。例如这里从 foo: string 类型中推断出 foo: String。如果类型是对导入类型的引用,这里的推断结果会是 foo: null (与 any 类型相等),因为编译器没有外部文件的信息。
    • 在生产模式下,编译器会生成数组格式的声明来减少打包体积 (这里的 props 会被编译成 ['foo', 'bar'])。
    • 生成的代码仍然是有着类型的 Typescript 代码,它会在后续的流程中被其它工具处理。
  • 截至目前,类型声明参数必须是以下内容之一,以确保正确的静态分析:现在还不支持复杂的类型和从其它文件进行类型导入。理论上来说,将来是可能实现类型导入的。
    • 类型字面量
    • 在同一文件中的接口或类型字面量的引用

使用类型声明时的默认 props 值

仅限类型的 defineProps 声明的不足之处在于,它没有可以给 props 提供默认值的方式。为了解决这个问题,提供了 withDefaults 编译器宏:

interface Props {
  msg?: string
  labels?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  msg: 'hello',
  labels: () => ['one', 'two']
})

上面代码会被编译为等价的运行时 props 的 default 选项。此外,withDefaults 辅助函数提供了对默认值的类型检查,并确保返回的 props 的类型删除了已声明默认值的属性的可选标志。

尾言:

这是Yang学习前端的第二个月了,Yang的前端之路才刚刚开始,希望几年后的Yang能感谢今天自己的坚持
共勉