# vue3-study **Repository Path**: Zzr4/vue3-study ## Basic Information - **Project Name**: vue3-study - **Description**: vue3-studyvue3-studyvue3-studyvue3-studyvue3-study - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-01-23 - **Last Updated**: 2024-01-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## Vue3 ### 起步 #### 安装 ~~~javascript npm create vue@latest ~~~ ### 组合式API #### 入口 ~~~javascript setup(){ //return XXXX } 或者 ~~~ **注意**: ​ 1:使用setup函数时,必须将模板中需要使用的数据return出去 ​ 2:setup中无法使用this指向组件实例 ​ 3:setup执行在beforeCreate生命周期之前 #### ref&&reactive **reative()**:接受**对象类型**的数据作为对象传入并返回一个响应式数据 ~~~java //定义 const state = reactive({num:1}) //使用 const setCount = () => { state.num++ }
{{state.num}}
~~~ **ref()**:接受**简单类型和对象类型的数据**传入并返回一个响应式**对象** ~~~javascript //定义 const state = ref(1) //使用:脚本区域使用ref产生的对象需要使用.value const setCount = () => { state.value++ } // 模板中不需要.value
{{state}}
~~~ #### couputed()计算属性 ~~~javascript const arr = ref([1,2,3,4,5,6,7]) // 使用变量接受computed中函数return的值 const newArr = computed(()=>{ return arr.filter(item => item>2) }) ~~~ #### watch()监听 ~~~javascript // 监听单个响应式数据变化,作为第一个属性的话ref对象不需要加.value const count = ref(0) const add = ()=>{ count.value++ } watch(count,(newVal,oldVal)=>{ console.log(newVal,oldVal) }) // 监听多个响应式数据变化,同时监听多数数据源,不管那个数据变化都执行回调 watch([count,name],([newVal,newVal2],[oldVal,oldVal2])=>{ console.log(newVal,oldVal) console.log(newVal2,oldVal2) },{immediate:true,deep:true}) // 精确监听对象中的某个属性 watch( ()=>count.value.num, (newVAl, oldVal) => { // XXXX }) ~~~ #### 生命周期函数 ~~~javascript setup() onBeforeMount() onMounted() onBeforeUpdate() onUpdated() onBeforeUnmount() onUnmounted() ~~~ 生命周期函数可以多次使用,按顺序执行 #### 父子通信 **父传子** 子组件通过defineProps函数接收 ~~~javascript // 父组件 // 子组件,defineProps不能用在生命周期函数中 const props = defineProps({message:String}) props.message ~~~ **子传父** 子组件通过defineEmits 生成emit方法,通过触发自定义的emit事件通知父组件 父组件通过事件监听获取 ~~~javascript // 子组件 const emits = defineEmits(['changeInfo']) const changeInfo = ()=>{ emits('changeInfo','111') } // 父组件接收 ~~~ #### 模板引用 ~~~javascript // 定义一个空的ref对象 const divRef = ref(null) // 模板中绑定ref
// 使用 onMounted(()=>{ console.log(divRef.value) }) ~~~ 如果需要通过ref获取子组件内的属性或者方法,需要使用defineExpose() ~~~javascript // 子组件 defineExpose({xx}) //父组件,子组件内的变量使用时如果也是ref响应式,直接使用定义时的值,不需要再套value sonRef.value.xx ~~~ #### provide&&inject ~~~javascript // 顶层组件 provide('key',顶层组件的数据或者ref对象或者方法名) // 底层组件 const message = inject('key') ~~~ 底层组件要修改顶层组件传过来的数据,不能直接修改,需要使用顶层组件传递得方法 ## TS 强类型语言 ### 起步 #### 搭建编译环境 ~~~javascript // 安装编译引擎 npm i -g typescript // 运行编译命令 tsc xx.ts // 工程化环境 npm create vite@latest 项目名 -- --template vanilla-ts ~~~ ### 类型注解 给变量添加类型约束,变量只能赋值为约定好的类型并且有相关的类型提示 ![1706097162347](assets/1706097162347.png) #### 简单类型 number、string、boolean、null、undefined #### 复杂类型 array、函数类型 ~~~javascript //限制数组类型和成员类型 let arr:number[] = [1,2,3] //泛型写法 let arr:Array=[1,2,3] ~~~ #### 可选参数 ~~~javascript // 函数类型可以注解形参和返回值 function add(a:number,b:number):number { return a + b } const add = (a:number,b:number):number => { return a + b } //函数整体注解(利用类型别名) type AddFn = (a:number,b:number) => number const add:AddFn = (a,b) => { return a + b } // 可选参数,使用?: // 可选参数必须在所有参数的末尾 // 函数无返回值使用void注解 function fn(a?:number):void{ //XXX } ~~~ #### 联合类型 多个类型合并为一个类型对变量进行注解 ~~~javascript // 可以存放数组,数组成员可以是数字和字符串 let arr:(number | string)[] = ['1',2] // 可以存放字符串或者成员为数字的数组 let arr:number | string[] = ['1',2] ~~~ #### 类型别名type 通过**type**关键词,给类型起一个名字来进行复用,也可以通过type注解对象、函数 同名的type会报错 ~~~javascript type ItemType = (number | string)[] let arr:ItemType = ['1',2] //注解对象 type Person = { name:string, } const obj:Person = { name:'张三' } ~~~ #### 接口类型interface ##### 接口的定义 描述对象数据类型。常用于给对象的属性和方法添加类型约束 ~~~javascript interface Person { name:string, age:num } const obj:Person = { name:'11', age:8 } ~~~ 一旦注解接口类型之后,对象的属性和方法类型都需要满足要求,并且属性不能多也不能少,但可以使用可选参数去避免这种情况报错 ![1706100097566](assets/1706100097566.png) ![1706100174687](assets/1706100174687.png) 同名的interface会合并,但是同一属性名不能出现类型冲突 ![1706101389070](assets/1706101389070.png) ##### 接口的继承extends 当接口的类型可以复用时,可以使用extends实现接口的继承实现复用 ~~~javascript interface FatherType { id:string, name:string } interface SonType extends FatherType { price:number } ~~~ #### 交叉类型& 可通过配合类型别名`type`实现模拟继承 ~~~javascript type Goods = { id:string, name:string } type GoodsPrice = Goods & { price:number } ~~~ #### 字面量类型 使用js字面量对变量进行类型注解 ~~~javascript let count:100 // count只能赋值为100 type Sex = '男'|'女' ~~~ ![1706101871417](assets/1706101871417.png) #### any类型 变量被注解为any类型之后,ts会忽略类型检查,错误的类型赋值不会报错也不会有任何提示 ![1706102597902](assets/1706102597902.png) #### 类型推论 1.声明变量并赋值时 2.决定函数返回值时 ![1706102414206](assets/1706102414206.png) #### 类型断言as 让类型更加精确和具体 ![1706102951211](assets/1706102951211.png) #### 泛型Generics 在定义接口或者函数等类型时,不预先指定具体的类型,在使用时再指定类型,方便类型复用 1.找到可变的类型部分,通过泛型``抽象为泛型参数 2.使用泛型时,把具体类型传入到泛型参数位置 ##### 泛型别名和泛型接口 ~~~javascript interface ResData { code:number, msg:string, data:T } type DataType = { name:string, id:number } const obj:ResData = { code:1, msg:'成功', data:{ name:张三, id:1 } } ~~~ ##### 泛型函数 ~~~javascript //函数的第二个形参不固定类型 function fn(a:number,b:T):any[]{ return new Array(a).fill(b) } fn(1,100) // [100] fn(2,'100') // ['100','100'] ~~~ ##### 泛型约束 解决需要在泛型函数的内部访问一些特定类型的数据才有的属性时,出现的类型错误 ~~~javascript interface AttrLen { length:number } function fn(a:number,b:T):any[]{ console.log(b.length) return new Array(a).fill(b) } fn(1,100) // 报错 fn(2,'100') // 3 ~~~