VUE3&TS: Vue3+TS基础编码的学习总结【不定时更新】

前言

整理一下所知道的 Vue3 + TS 的基础知识点【会不定时更新】。

一、理解

若还没看过 Vue3文档 或 TS搭配Vue3使用 的官方文档的童鞋,还是记得看看 官方文档

1. 静态类型、动态类型、强类型、弱类型

编译时就知道变量类型的是静态类型,运行时才知道一个变量类型的叫做动态类型。 java 是静态类型, js 是动态类型。

不允许隐式转换的是强类型,允许隐式转换的是弱类型。 java 是强类型, js 是弱类型。

那ts到底是什么类型的语言,很明显, ts 是静态类型语言,因为它需要经过编译。但是 ts不是强类型,因为它可以允许隐式类型转换。

let isBool: boolean
let num: number = 10
isBool = !num // ok

2. Typescript是什么

ECMAScript 的超集 (stage 3)
编译期的类型检查
不引入额外开销(零依赖,不扩展 js 语法,不侵入运行时)
编译出通用的、易读的 js 代码
Typescript = Type + ECMAScript + Babel-Lite

3. 为什么使用 Typescript

增加了代码的可读性和可维护性
减少运行时错误,写出的代码更加安全,减少 BUG
享受到代码提示带来的快感
重构神器

二、知识点

注意

<script set lang="ts">
// 代码片段....
</script>

1. 基础类型

声明了变量的类型,那么这个变量就有了静态类型的特性,ts中使用:操作符来声明类型。

  • boolean
  • number
  • string
  • array
  • tuple(元组)
  • enum
  • any & unknow
  • void
  • null & undefind
  • never
  • Object

1.1 boolean、number、string

  // boolean 类型
  let bool: boolean = true
  console.log(bool)

  // number 类型
  // 支持浮点数、十进制和十六进制字面量、ES5的二进制和八进制字面量
  let decLiteral: number = 6
  let hexLiteral: number = 0xf00d
  let binaryLiteral: number = 0b1010
  let octalLiteral: number = 0o744

  // string 类型
  let str: string = 'hellow word'
  let strL: string = `---${str}的字符串长度是${str.length}`

1.2 array

1.2.1 指定类型的数组

在元素类型后面接上 [],表示由此类型元素组成的一个数组。

  let numArr: number[] = [1, 2, 3]
  let anyArr: any[] = [1, '2', true]
1.2.2 泛型数组
  // Array<元素类型>
  let arrNum: Array<number> = [1, 2, 3]

1.3 tuple元组

元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。
Ts 内置类型之 Tuple

  let tupleArr1: [string, number]
  tupleArr1 = ['', 0] // ok
  tupleArr1 = [1, false] // error

  let tupleArr2: [number, string, boolean] = [1, '2', false] // ok

1.4 enum枚举

  • 数字枚举
  • 字符串枚举
  • 常量枚举

TS中,枚举就是一组常量的集合,但是和集合不同,枚举可以通过变量的值来得到变量,它是一个双向的过程。

1.4.1 数字枚举

默认的,第一个变量的值是0,后面的值会在前一个值上 +1,以此类推。是支持正反映射的。

  enum PositionTypes {
    TOP,
    RIGHT,
    BOTTOM,
    LEFT
  }
  // 用值,则会得到 属性名的字符串
  const top1 = PositionTypes[0] // TOP
  // 用指定属性,则会得到 值
  const top2 = PositionTypes.TOP // 0
  console.log(top1, top2)

想改变枚举的初始值,只需要给第一个变量赋值即可。

  enum PositionTypesNum {
    TOP = 2,
    RIGHT,
    BOTTOM,
    LEFT
  }
  // 用值,则会得到 属性名的字符串
  const topNum1 = PositionTypesNum[2] // TOP
  // 用指定属性,则会得到 值
  const topNum2 = PositionTypesNum.TOP // 2
  console.log(topNum1, topNum2)

赋值重复的时候,调用会返回最后一个。

  enum PositionTypesNum {
    TOP = 2,
    RIGHT = 2,
    BOTTOM,
    LEFT
  }
  const topNum1 = PositionTypesNum[2] // RIGHT
  const topNum2 = PositionTypesNum.TOP // 2
  console.log(topNum1, topNum2)

当枚举值不是数字的时候,下一个必须设置枚举值。

  enum demoTypesAny3 {
    a, // a=0
    b = 3, // b=3
    c, // c=4
    e = 'q1', // e="q1"
    f = 5 // f=5,此处不能直接写f
  }
  console.log(demoTypesAny3)
1.4.2 字符串枚举

在一个字符串枚举里,每个成员都必须初始化值,否则会报错。

  enum PositionTypesStr {
    TOP = 'top',
    RIGHT = 'right',
    BOTTOM = 'bottom',
    LEFT = 'left'
  }
  // 字符串枚举,就只能用属性名取值了
  const topStr = PositionTypesStr.TOP // 'top'
  console.log(topStr)

当等号左侧和右侧重复的时候,左侧优先

  enum demoTypesStr1 {
    a = 'b',
    b = 'a',
    c = 'a'
  }
  const demo1 = demoTypesStr1['a'] // 'b'
  const demo2 = demoTypesStr1.a // 'b'
  console.log(demo1, demo2)
1.4.3 常量枚举

用 const 修饰符来声明枚举,编译后的 JS 代码将不会出现额外的声明代码。

const 枚举只能在属性或索引访问表达式中使用,或者在导入声明或导出赋值或类型查询的右侧使用,如不可console。

  enum PositionTypes2 {
    UP,
    DOWN,
    LEFT,
    RIGHT
  }
  const enum PositionTypes22 {
    SPRING = 'SPRING',
    SUMMER = 'SUMMER',
    AUTUMN = 'AUTUMN',
    WINTER = 'WINTER'
  } // 编译后看不到
  const up = PositionTypes2.UP
  const spring = PositionTypes22.SPRING
  console.log(up, spring) // 0 'SPRING'

1.5 any 和 unknown

any(任意类型),unknown(未知的类型)。
任何类型都能分配给 unknown ,但 unknown 不能分配给其他基本类型,而 any 都能分配和被分配。

  // any demo
  let testAny: any
  testAny = true // ok
  testAny = 123 // ok
  testAny.toFixed(2) // ok
  let testAny1: string = testAny // ok
  console.log(testAny1) // 123

  //  unkonwn demo
  let testUnknown: unknown
  testUnknown = true // ok
  testUnknown = 123 //ok
  testUnknown.toFixed(2) // error
  let testUnknown1: string = testUnknown // error
  console.log(testUnknown) // 123

用了 any 就相当于完全丢失了类型检查,所以尽量少用 any ,对于未知类型可以用 unknown。使用时,尽量将类型范围缩小,方式多样。

  function getLength(value: unknown): number {
    if (typeof value === 'string') {
      // 因为类型保护的原因,此处 value 被判断为 string 类型
      return value.length
    }
    return 0
  }
  console.log(getLength('aabbccdd')) // 8
  console.log(getLength(0.001)) // 0

1.6 void

表示没有任何类型,一般用于定义方法的时候没有返回值。
声明一个 void 类型的变量没有什么大用,因为你只能为它赋予 undefined 和 null。

  // ts定义方法 没有返回值时写 void类型
  function doSomeThing(val): void {
    console.log(val)
  }
  console.log(doSomeThing('哈哈哈哈')) // undefined

  // 有返回值的时候根据规定的类型返回值,否则会保错
  function getResFun():number{
    // return '' // error
	return 123
  }
  console.log(getResFun()) // 123

1.7 null 和 undefined

默认情况下 null 和 undefined 是所有类型的子类型。
可以把 null 和 undefined 赋值给 number 等其他类型的变量。

1.7 never

表示的是那些永不存在的值的类型,不可以被never以外的值类型所赋值。

never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型;
变量也可能是 never类型,当它们被永不为真的类型保护所约束时。

是任何类型的子类型,可以赋值给任何类型。

没有类型是never的子类型或可以赋值给never类型(除了never本身之外),即使 any 也不可以赋值给 never。
  // 返回never的函数必须存在无法达到的终点
  function error(message: string): never {
    throw new Error(message);
  }
  // 推断的返回值类型为never
  function fail() {
    return error("Something failed");
  }
  // 返回never的函数必须存在无法达到的终点
  function infiniteLoop(): never {
    while (true) {
    }
  }

never 还可以用于联合类型的单位元

  type T0 = string | number | never // => type T0 = string | number
  let a: T0
  a = 1
  console.log(a) // 1

1.8 object

object表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型。

  // 在目前TS最新的3.1版本及之前,不推荐使用object类型
  function create(o: object | null) {
    return o
  }

  // 更容易检查和使用键值
  function create(o: Record<string, unknown> | null) {
    return o
  }
  create({ prop: 0 }) // OK
  create(null) // OK

2. 接口

// TODO…

3. 类

// TODO…

4. 高级类型

4.1 联合类型

表示多种类型的 “或” 关系,一个值可以是几种类型之一。

  function getLength(val: string | any[]) {
    return val.length
  }
  const strLen = getLength('') // ok
  const arrLen = getLength([]) // ok
  const otherLen = getLength(1) // error
  console.log(strLen, arrLen) // 0 0

注意
若联合类型是复杂的,那么调用里面的方法等时,需要满足对应的条件,否则报错,后面的 类型保护 中有介绍如何进行处理。

  interface Bird {
    name: string
    age: number
  }
  interface Fish {
    name: string
    codes: string[]
  }
  function getSmallPet(val: Bird | Fish) {
    console.log(val.name) // ok
    console.log(val.codes) // error
  }
  getSmallPet({ name: '111', age: 1 })

4.2 交叉类型

表示多种类型的 “与” 关系。
需要有 定义的声明类型 的所有字段,否则error。

  interface Person {
    name: string
    age: number
  }
  interface Color {
    name: string
    codes: string[]
  }
  const people: Person & Color = {
    name: 'people',
    age: 2,
    codes: ['11', '22']
  }
  console.log(people)

4.3 使用联合类型表示枚举

可以避免使用 enum 侵入了运行时。

  // type 关键词可以声明一个类型
  type PositionType1 = 'UP' | 'DOWN' | 'LEFT' | 'RIGHT'
  const posVal: PositionType1 = 'UP'
  console.log(posVal) // 'UP'

  // 具值联合类型
  type PositionType2 = 'top' | 'center' | 'bottom'
  let posTypeVal: PositionType2 = 'top' // ok
  posTypeVal = 'left' // error 不能将类型 "left" 分配给类型 "PositionType2"
  posTypeVal = 'bottom' // ok
  console.log(posTypeVal) // 'bottom'

  // 数组联合类型
  const arr: (number | string)[] = []
  arr.push(1) // ok
  arr.push('hello') // ok
  arr.push(true) // error 类型 "true" 的参数不能赋给类型 "string | number" 的参数。
  console.log(arr) // [1, 'hello']

type 与 interface 的区别

4.4 类型保护和类型断言

使用 TS 的 is 关键词

  function isString(value: unknown): value is string {
    return Object.prototype.toString.call(value) === '[object String]'
  }
  function isNumber(value: unknown): value is number {
    return Object.prototype.toString.call(value) === '[object Number]'
  }
  function fn(val: string | number) {
    if (isString(val)) {
      return val.length
    } else if (isNumber(val)) {
      return undefined
    }
  }
  const val1 = 111
  const val2 = '222'
  console.log(fn(val1), fn(val2)) // undefind 3
4.4.1 类型保护
(1)typeof 类型保护

typeof 返回一个表达式的数据类型的字符串,返回结果为 JS 基本的数据类型,包括number,boolean,string,object,undefined,function。语法为 typeof(data) 或 typeof data。

  function getNumber(value: string | number) {
    if (typeof value === 'number') {
      return value
    }
    if (typeof value === 'string') {
      return Number(value)
    }
    throw new Error(`Expected string or number, got '${value}'.`)
  }
  getNumber(1) // ok
  getNumber('111') // ok
  getNumber(false) // error
  function getLen(x: string | any[]) {
    return x.length
  }
  type GetLen = typeof getLen
  function callback(fn: GetLen) {
    fn(1) // error: 类型为 'number'的参数不能赋值给类型为 'string | any[]' 的参数
    fn('11') // ok
  }
(2)instanceof 类型保护
  class CreateByClass1 {
    public age = 18
    constructor() {
      this.age
    }
  }
  class CreateByClass2 {
    public name = 'TypeScript'
    constructor() {
      this.name
    }
  }
  function fn1(x: CreateByClass1 | CreateByClass2 | string) {
    if (x instanceof CreateByClass1) {
      return x.age
    } else if (x instanceof CreateByClass2) {
      return x.name
    } else {
      return x.length
    }
  }
(3)针对 null 和 undefined 的类型保护

在条件判断中,TS 会 自动nullundefined 进行类型保护。

  function fn2(x: string) {
    if (x) {
      return x.length
    }
  }
  fn2('111') // ok
  fn2() // error
  fn2(null) // error
  fn2(undefined) // error
4.4.2 类型断言
(1)类型断言:as

把一个大的范围断言成小的、精确的范围。

  type Method = 'GET' | 'POST'
  function toDo(url: string, method: Method) {
    console.log(url, method)
  }
  let option1 = {
    url: 'https:',
    method: 'POST'
  }
  // toDo(option.url, option.method) 第二个参数会报错的,因为 option.method 的值是个字符串类型,而不是自己定义的Method类型
  //可以用类型断言 as 因为string类型是大的范围,缩小到'POST'和'GET'这种小范围的类型
  toDo(option1.url, option1.method as Method) // https: POST

  //当然也可以给option定义一个类型
  type getOption = {
    url: string
    method: Method
  }
  let option2: getOption = {
    url: 'https:',
    method: 'POST'
  }
  toDo(option2.url, option2.method) // https: POST
(2)非空类型断言:!

表示确定某个标识符是有值的,跳过ts在编译阶段对它的检测。
不推荐使用非空类型断言。

  function bb(value: string = '') {
    //加上 ! 的意思是确保value一定是有值的
    console.log(value!.length)
  }
  bb('ppp')
(3)可选链操作符:?

其作用是当对象的属性不存在时,会短路,直接返回undefined,如果存在,那么才会继续执行。
函数的参数后加 ? 标识可选参数,即表示允许undefined。
x?: string 等价于 x: string | undefined。

  // x?: string 等价于 x: string | undefined
  function fn3(x: string) {
    if (x) {
      return x.length
    }
  }
  fn3('111')
  // fn2(undefined) // error: 类型为 'undefined' 的参数不能赋值给类型为 'string | undefined'的参数
  // fn2(null) // error
  function fn4(x: string | null | undefined) {
    if (x) {
      return x.length
    }
  }
  fn4(undefined) // ok
  fn4(null) // ok
  // 可选参数放置在最后
  function fn5(a: string, x?: string | null, y?: string) {
    console.log(a, x, y)
    if (a) {
      return a.length
    }
  }
  fn5('111') // 111 undefined undefined
(4)!! 和 ??

!! 将一个其他类型转换成boolean类型,类似于Boolean()。
?? 空值合并操作符,当操作符的左侧是null或者undefined时,返回其右侧操作数,否则返回左侧操作数。

  let ss: string | null | undefined = undefined
  console.log(ss ?? '你好') // ss ?? '你好' => 如果 ss有值而且不是null和undefined时,ss就是上面赋给的值,如果是null或者undefined,ss的值就是默认值'你好'

5. 特殊写法

5.1 通用

5.1.1 属性名不确定具体名字,但是值是可控的
interface Attr {
  [key: string]: string | number | null | undefind
}
5.1.2 参数是函数
const setFn = (fn: ((...arg: any[]) => void) | null) : boolean => {
  if (typeof fn !== 'function') {
    return false
  }
  console.log(fn)
  retrun true
}

5.2 Vue

5.2.1 组件参数 defineProps & withDefaults
(1)接收参数 defineProps
<script setup lang="ts">
interface PropsItem {
  resolutionName: string
  lineName: string[]
  videoUrl: string[]
  loop?: boolean
}

const props = defineProps<{
  autoPlay: boolean
  data: PropsItem[]
}>()

console.log(props)
</script>
(2)设置默认值 withDefaults
<script setup lang="ts">
interface PropsItem {
  size?: number,
  name?: string
}

const props = withDefaults(defineProps<PropsItem>(), {
  size: 50,
  name: 'supper'
})

console.log(props)
</script>
5.2.2 值是计算属性 ComputedRef
<script setup lang="ts">
import { type ComputedRef, ref } from 'vue'

interface TabMenu {
  title: string
  active?: ComputedRef<boolean> | boolean
}

const displayDown = ref(false)
const tabMenus = ref<TabMenu[]>([
  { title: 'tab1' },
  {
    title: 'tab2',
    active: computed(() => displayDown.value)
  }
])
</script>
5.2.3 多个子组件引入 shallowRef
import { shallowRef, type DefineComponent } from 'vue'
import componentOne from './componentOne.vue'

interface ImportComp {
  [key: string]: DefineComponent
}

const commonInfoContentRefs = shallowRef<ImportComp>({
  one:componentOne as DefineComponent,
  two:componentTwo as DefineComponent,
  three:componentThree as DefineComponent,
})

N. TODO…


最后

觉得有用的朋友请用你的金手指点一下赞,或者评论留言一起探讨技术!

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3中结合使用Element Plus和TypeScript时,可能会遇到`scope未定义`的问题。 这个错误通常出现在你使用了Element Plus的某个组件,但没有正确引入相应的作用域。 首先,确保你已经安装并引入了Element Plus库。可以通过以下命令进行安装: ``` npm install element-plus ``` 然后,在你的代码中,通过`import`语句将需要使用的Element Plus组件引入到你的文件中。例如,如果你想使用`el-button`组件,可以这样引入: ```typescript import { ElButton } from 'element-plus' ``` 接下来,在Vue组件中,将引入的组件在`components`中进行注册。例如: ```typescript export default { components: { ElButton }, // ...其他组件选项 } ``` 现在,你可以在模板中使用`ElButton`组件了。例如: ```html <template> <el-button>点击我</el-button> </template> ``` 如果在以上步骤完成后,仍然遇到`scope未定义`的问题,可能是因为你没有在`script`标签中声明包含Element Plus代码的`setup`函数。 在Vue3中,`setup`函数是用来进行组件的初始化和响应式数据的声明的。你需要确保将Element Plus的代码放在`setup`函数中。例如: ```typescript <script lang="ts"> import { defineComponent } from 'vue' import { ElButton } from 'element-plus' export default defineComponent({ components: { ElButton }, setup() { // 在这里使用Element Plus的代码 } }) </script> ``` 以上是解决`scope未定义`问题的一般步骤。如果问题仍然存在,可能是其他配置或代码问题导致的,可以进一步检查和调试。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值