vue3+ts

vue3.0、ts、pinia、vite七七八八汇总

    • ***JS***
    • ***ts***
    • ***vue 3.0***
    • ***vue3中单文件组件***
    • ***vite+vue3.0+ts+pinia项目搭建***

vue3+ts_第1张图片

cat ‘不是内部或外部命令…’ 用type代替cat
vue3+ts_第2张图片

JS

最新的ECMAScript标准定义了8种数据类型:

  • 7种原始类型:
    Boolean
    Null
    Undefined
    Number
    Biglnt
    String
    Symbol
  • 和 Object
    原始值:除Object以外的所有类型都是不可变的(值本身无法被改变)。

ts

1、基本数据类型

// 原始数据类型: Boolean;Null;Undefined;Number;BigInt;String;Symbol

let isDone: boolean = false

// es6 中 number还支持二进制和八进制
let age: number = 10
let binaryNumber: number = 0b1111

// 字符串类型,也可使用es6中的模板字符串
let firstName: string = 'wly'
let message: string = `hello, ${firstName}`

// undefinde 和 null 所有类型的子类型
let u: undefined = undefined
let n: null = null

// undefined类型可以赋值给number类型的变量[官方这么讲,但是我码出来就是报错,暂时还未知]
let num: number = undefined

// any类型
let notSure: any = 4
notSure = 'maybe a string'
notSure = false
notSure.myName  // 在任意值上访问任何属性都是允许的
notSure.getName()  // 也允许调用任何方法

2、数组Array和元组Tuple

// 数组
let arrOfNumbers: number[] = [1,2,3]  //定义数字类型的数组
arrOfNumbers.push(4)

function test() {
    console.log(arguments) //arguments 是一个对应于传递给函数的参数的类数组对象。
    
}

function func1(a, b, c) {
    console.log(arguments[0])  // 1
    console.log(arguments[1])  // 2
    console.log(arguments[2])  // 3
}
func1(1, 2, 3)

// 元组Tuple 声明几个类型就能写几个,不能多写少些
let user: [string, number] = ['wly', 123]
user.push(12)  //但是可以push,push的值只能是string、number-联合类型

3、interface接口

// 定义一个接口 IPerson
interface IPerson {
    readonly id: number;  //readonly只读属性
    name: string;
    age?: number;  //?可选属性,这一项可有可无,否则不可多项和少项
}

// 定义一个变量viking, 他的类型是IPerson
let viking: IPerson = {
    id: 1,
    name: 'viking'
}

4、函数

// 约定输入,约定输出
function add(x: number, y: number): number {
    return x + y
}

let result = add(1, 2)

// z是个可选参数
const add2 = (x: number, y: number, z?: number): number => {
    if(typeof z === 'number') {
        return x + y + z
    } else  {
        return x + y
    }
}

// 函数本身的类型,注意在函数类型里面返回类型是个箭头
const add3: (x: number, y: number, z?: number) => number = add2

// 接口里面返回类型是个冒号
interface ISum {
    (x: number, y: number, z?:number): number
}
let add4: ISum = add2

5、类型推论、联合类型、类型断言、类型守卫

let str = 'str'

// union types-联合类型 中间用竖线来分割
let umberOrString: number | string
umberOrString = 1
umberOrString.toString()  // 只能访问此联合类型里共有的属性或方法

// type assertions-类型断言 as作为关键字-当编辑器无法判断我的代码,但是本人很清楚,我把它成string,你也可以用string方法
function getLength(input: string | number): number {
    const str = input as string
    if(str.length) {
        return str.length
    } else {
        const number = input as number
        return number.toString().length
    }
}

//type guard-类型守卫 在不同条件的分支里面,智能缩小范围,降低代码出错
function getLength2(input: string | number): number {
    if(typeof input === 'string') {
        return input.length
    } else {
        return input.toString().length
    }
}

6、枚举

// 数字枚举 关键词enum, 我们定义了一系列得方向,这里得值,枚举成员会被赋值为从 0 开始递增的数字
enum Direction {
    Up,
    Down,
    Left,
    Right
}
console.log(Direction.Up)  // 0
console.log(Direction[0])  // Up // 这个枚举还做了反向映射

enum Direction2 {
    Up = 'up',
    Down = 'down',
    Left = 'left',
    Right = 'right'
}
const value = 'up'
if(value === Direction2.Up) {
    console.log('go up!!')
}

// 常量枚举
const enum Direction3 {
    Up = 'UP',
    Down = 'DOWN',
    Left = 'LEFT',
    Right = 'RIGHT'
}
const value3 = 'UP'
if(value3 === Direction3.Up) {
    console.log("go up!!!")
}// An highlighted block
var foo = 'bar';

注意字符串枚举跟常量枚举最本质得区分就是js中,字符串枚举只会执行Direction3.Up,其余在Direction3得其他属性值都不会执行
vue3+ts_第3张图片

7、泛型

function echo<T>(arg: T):T {
    return arg
}
// const str: string = 'str'
// const result = echo(str)

const result1 = echo(123)

function swap<T, U>(tuple: [T, U]):[U, T] {
    return [tuple[1], tuple[0]]
}
const result2 = swap(['string', 123])


// 约束泛型
function echoWithArr<T>(arg: T[]):T[] {
    console.log(arg.length)
    return arg
}
const arrs = echoWithArr([1, 2, 3])


interface IWithLength {
    length: number
}
function echoWithArrLength<T extends IWithLength>(arg: T): T {
    return arg
}
const str = echoWithArrLength('str')
const obj = echoWithArrLength({ length: 10, width: 10 })
const arr2 = echoWithArrLength([1, 2, 3])
echoWithArrLength(13)  // number里面没有length属性,所以报错


// 类的公有类型(public)和私有类型(private)
class Queue<T> {
    private data: T[] = [];
    push(item: T) {
        return this.data.push(item)
    }
    pop() {
        return this.data.shift()
    }
}
const queue = new Queue<number>()
queue.push(1)
const popedValue = queue.pop()
if(popedValue) {
    console.log(popedValue.toFixed())
}


// 泛型和interface
interface KeyPair<T, U> {
    key: T
    value: U
}
let kp1: KeyPair<number, string> = {key: 1, value: 'string'}
let kp2: KeyPair<string, number> = {key: 'str', value: 2}
let arr: number[] = [1, 2, 3]
let arrTwo: Array<number> = [1, 2, 3]

8、类型别名 和 交叉类型

// 类型别名 和 交叉类型

import { type } from "os"

let sum: (x: number, y: number) => number
const result = sum(1, 2)
type PlustType = (x: number, y: number) => number
let sum2: PlustType
const result2 = sum2(2,3)

// 支持联合类型
type StringOrNumber = string | number
let result3: StringOrNumber = '123'
result3 = 123

const str: 'name' = 'name'
const number: 1 = 1

// 字符串字面量
type Direcions = 'Up' | 'Down' | 'Left' | 'Right'
let toWhere: Direcions = 'Left'

// 交叉类型
interface IName {
    name: string
}
type IPerson = IName & {age: number}
let person: IPerson = {name: '123', age: 123}

9、声明文件
(1)axios.d.ts //注.d.ts固定写法
注:这两个文件需要同时在编辑器中打开,不然axio会报错

// 它里面没有任何的实际实现代码,只有类型声明
// 只有类型 - 比如 interface,funciton 或者 class 等等

// declare function axios(url: string): string
interface IAxios {
    get: (url: string) => string;
    post: (url: string, data: any) => string
}
declare const axios: IAxios  // declare 声明类型

declaration-files.ts

// axios('test.url')
axios.get('url')
axios.post('url', {name: 'viking'})

(2) 引入第三方声明文件
npm i axios
declaration-files.ts

import axios from 'axios'
axios.get('ulr')
axios.post('url', {name: 'viking'})

(3)声明文件-小例子 计算器

//第一种
// caculator.d.ts
type IOperator = 'plus' | 'minus'
type ICalculator = (operator: IOperator, numbers: number[]) => number
declare const calculator: ICalculator
// declaration-files.ts
calculator('minus', [1,2])
// 第二种
// caculator.d.ts
type IOperator = 'plus' | 'minus'
interface ICalculator {
	(operator: IOperator, numbers: number[]): number;
	plus: (numbers: number[]) => number;
	minus: (numbers: number[]) => number;
}
declare const calculator: ICalculator
export default calculator // 也可以使用es6
// declaration-files.ts
import calculator from './calculator'
calculator.minus([1,3])

将第二种的caculator.d.ts代码,挪到node_modules下的@types中创建文件夹caculator里面建立文件index.d.ts里面(作为模块来使用)

// declaration-files.ts
import calculator from 'calculator'

10、内置类型

const a: Array<number> = [1, 2, 3]
// 大家可以看到这个类型,不同的文件中有多处定义,但是它们都是 内部定义的一部分,然后根据不同的版本或者功能合并在了一起,一个interface 或者 类多次定义会合并在一起。这些文件一般都是以 lib 开头,以 d.ts 结尾,告诉大家,我是一个内置对象类型欧
const date: Date = new Date()
date.getTime()
const reg = /abc/
// 我们还可以使用一些 build in object,内置对象,比如 Math 与其他全局对象不同的是,Math 不是一个构造器。Math 的所有属性与方法都是静态的。
reg.test('abc')

Math.pow(2, 2)

// DOM 和 BOM 标准对象
// document 对象,返回的是一个 HTMLElement
let body: HTMLElement = document.body
// document 上面的query 方法,返回的是一个 nodeList 类型
let allList = document.querySelectorAll('li')
allList.keys()

//当然添加事件也是很重要的一部分,document 上面有 addEventListener 方法,注意这个回调函数,因为类型推断,这里面的 e 事件对象也自动获得了类型,这里是个 mouseEvent 类型,因为点击是一个鼠标事件,现在我们可以方便的使用 e 上面的方法和属性。
document.addEventListener('click', (e) => {
    e.preventDefault()
})


interface IPerson {
    name: string,
    age: number
}
let viking: IPerson = { name: 'viking', age: 20 }
type IPartial = Partial<IPerson>
let viking2: IPartial = { name: 'viking'}
type IOmit = Omit<IPerson, 'name'>  // IPerson name属性忽略掉
let viking3: IOmit = { age: 20 }

11、配置文件

{
  "files": ["test.ts", "test2.d.ts"],
  "compilerOptions": {
    "outDir": "./output",
    "module": "ESNext",
    "target":"ES5",
    "declaration": true
  }

vue 3.0

vue3
vue-cli

vue-ui 图形化界面创捷项目
vite脚手架 不同于vue-cli的创新

// vue 3.0推荐vscode种volar插件,注将原来vetur禁掉

// 查看项目下的eslint版本

vue3+ts_第4张图片
在这里插入图片描述
vite:https://cn.vitejs.dev/

vscode中之前用的插件是vetur,vue3.0用的插件是volar
ref
// 注:ref定义变量读取的时候写法是 该变量名.value

<template>
  <h1>{{ count }}</h1>
  <button @click="increase">ddddd</button>
  <h2>{{ double }}</h2>
</template>

<script lang="ts">
// ref 是一个函数,它接受一个参数,返回的是一个神奇的 响应式对象。我们初始化的这个0作为参数包裹到这个对象中去,在未来可以检测到改变并作出对应的响应
import  { defineComponent, ref, computed } from 'vue';
export default defineComponent({
  name: 'App',
  setup() {
    const count = ref(0)
    const double = computed(() => {
      return count.value * 2
    })
    const increase = () => {
      count.value++
    }
    return {
      count,
      increase,
      double
    }
  }
});
</script>

<style></style>

reactive、toRefs
使用ref还是reactive可以选择准则
(1)就像刚才的原生javascript的代码一样,像你平常写普通的js代码选择原始类型和对象类型一样来选择使用ref还是reactive
(2)所有场景使用reactive,但要记得使用toRefs保证reactive
对象属性保持响应性

<template>
  <h1>{{ count }}</h1>
  <button @click="increase">ddddd</button>
  <h2>{{ double }}</h2>
</template>

<script lang="ts">
import  { defineComponent, computed, reactive, toRefs } from 'vue';
interface DataProps {
  count: number;
  double: number;
  increase: () => void
}
export default defineComponent({
  name: 'App',
  setup() {
    const data: DataProps = reactive({
      count: 0,
      increase: () => {
        data.count++
      },
      double: computed(() => data.count * 2)
    })
    const refData = toRefs(data)
    return {
      ...refData
    }
  }
});
</script>

<style>
</style>

生命周期

vue 2.0 -> vue 3.0
beforeCreate -> use setup()
created -> use setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
activated -> onActivated
deactivated -> onDeactivated
errorCaptured -> onErrorCaptured

//调试 debugger钩子函数
onRenderTracked
onRenderTriggered

watch

 // watch 简单应用
    watch(data, () => {
      document.title = 'update' + data.count
    })
    // watch的两个参数,代表新的值和旧的值
    watch(refData.count, (newValue, oldValue) => {
      console.log("oldValue=",oldValue)
      console.log("newValue", newValue)
      document.title = 'update' + data.count
    })
    // watch多个值,返回的也是多个值的数组
    watch([greetings, data], (newValue, oldValue) => {
      console.log("oldValue", oldValue)
      console.log("newValue", newValue)
      document.title = 'updated' + greetings.value + data.count
    })
    // 使用greetings的写法watch reactive 对象中的一项
    watch([greetings, () => data.count], (newValue, oldValue) => {
      console.log('oldValue', oldValue)
      console.log("newValue", newValue)
      document.title = 'updated' + greetings.value + data.count
    })

hooks
vue3的hooks函数相当于vue2的mixin,不同在与hooks是函数
vue3的hooks函数可以提高代码的复用性,可以在不同组件中利用hooks函数
例:
1、在src目录下创建一个hooks文件夹
2、创建文件名.ts
vue3+ts_第5张图片
useMousePosition.ts

import { ref, onMounted, onUnmounted} from 'vue'
function useMousePosition() {
    const x = ref(0)  // x绑定响应式数据
    const y = ref(0)
    const updateMouse = (e: MouseEvent) => {
      x.value = e.pageX
      y.value = e.pageY
    }
    onMounted(() => {
      document.addEventListener('click', updateMouse)
    })
    onUnmounted(() => {
        document.removeEventListener('click', updateMouse)
    })
    return {x, y}
}
export default useMousePosition

在***.vue中

<template>
  <div>
    <h1>x{{x}}</h1>
    <h1>y{{y}}</h1>
  </div>
</template>

<script lang="ts">
import  { defineComponent,ref, computed, reactive, toRefs, watch, onMounted, onUnmounted} from 'vue';
import useMousePostion from './hooks/useMousePosition'
export default defineComponent({
  name: 'App',
  setup() {
    const { x, y } = useMousePostion()
    return {
      x,
      y
    }
  }
});
</script>

reactive版本

import { reactive, toRefs, onMounted, onUnmounted } from 'vue'
interface UseMouse {
    x: number,
    y: number
}
function useMousePosition() {
    const useMouse: UseMouse = reactive({
        x: 0,
        y: 0
    })
    const updateMouse = ((e: MouseEvent) => {
        useMouse.x = e.pageX
        useMouse.y = e.pageY
    })
    onMounted(() => {
        document.addEventListener('click', updateMouse)
    })
    onUnmounted(() => {
        document.removeEventListener('click', updateMouse)
    })
    return {
        ...toRefs(useMouse)
    }
}
export default useMousePosition

vue3中单文件组件

一、相比普通script语法的优势

script setup>是在单文件组件(SFC)中使用组合式API的编译时语法糖。相比于普通的

  1. 更少的样板内容,更简洁的代码
  2. 使用纯TypeScript声明props和抛出事件
  3. 更好的运行时性能(其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)
  4. 更好的IDE类型推断性能(减少语言服务器从代码中抽离型的工作)

二、基本语法

// 需要将setup attribute添加到
                    
                    

你可能感兴趣的:(javascript,前端,typescript)