# 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
~~~
### 类型注解
给变量添加类型约束,变量只能赋值为约定好的类型并且有相关的类型提示

#### 简单类型
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
}
~~~
一旦注解接口类型之后,对象的属性和方法类型都需要满足要求,并且属性不能多也不能少,但可以使用可选参数去避免这种情况报错


同名的interface会合并,但是同一属性名不能出现类型冲突

##### 接口的继承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 = '男'|'女'
~~~

#### any类型
变量被注解为any类型之后,ts会忽略类型检查,错误的类型赋值不会报错也不会有任何提示

#### 类型推论
1.声明变量并赋值时
2.决定函数返回值时

#### 类型断言as
让类型更加精确和具体

#### 泛型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
~~~