VUE3
1.入门
1.创建工程
1.Vue3
vue-cli构建(vue2构建方式相同)
vite
npm init vite-app 工程名
cd …
npm i
npm run dev
2.特点
Vue3组件可以不用写div根目录
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Hello Vue 3.0 + Vite" />
</template>
2.Composition API
1.Setup
返回一个对象(常用)
export default {
name: 'App',
setup(){
let name = '张三';
let age = 33;
function echo(){
alert(name+age)
}
return {
name,
age,
echo
}
}
}
注意事项
vue2和setup不要混用
如果有重名setup优先
setup不能是一个async函数,因为返回值是promise而不是return的对象
2.ref函数
作用:定义一个响应式的数据
语法:
const xxx = ref(initValue)
创建一个包含响应式数据的引用对象(reference对象)。
JS中操作数据:
xxx.value
模板中读取数据: 不需要.value,直接:<div>{{xxx}}</div
备注:
接收的数据可以是:基本类型、也可以是对象类型。
基本类型的数据:响应式依然是靠 Object.defineProperty()的
对象类型的数据:内部“求助”了Vue3.0中的一个新函数——reactivelset完成的。
3.reactive函数
作用:定义一个对象类型的响应式数据(基本类型别用它,用ref 函数)
语法:
const 代理对象=reactive(被代理对象)接收一个对象(或数组),返回一个代理器对象(proxy对象)
reactive定义的响应式数据是“深层次的”。
内部基于 ES6的Proxy实现,通过代理对象操作源对象内部数据都是响应式的
4.Vue3实现响应式
Proxy
#region
let person = {
name:'zs',
age:33
}
const p = Proxy(person,{
get(target,propName){
console.log("get",target,propName);
},
set(target,propName,value){
console.log("set",target,propName);
target[propName]=value;
},
deleteProperty(target,propName){
console.log("deleteProperty",target,propName);
delete target[propName];
}
})
5.reactive对比ref
从定义数据角度对比:
ref用来定义:基本类型数据。
reactive用来定义:对象(或数组)类型数据。
备注:ref也可以用来定义对象(或数组)类型数据,它内部会自动通过reactive转为代理对象。
从原理角度对比:
ref通过 0bject.defineProperty()的get与set来实现响应式(数据劫持)。
reactive通过使用Proxy来实现响应式(数据劫持),并通过Reflect操作源对象内部的数据。
从使用角度对比:
ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value
reactive定义的数据:操作数据与读取数据:均不需要.value
3.计算属性和监视
1.computed
简写写法
let add = computed(()=>{
return strs.value+'1234';
})
完整写法
get(){}
set(){}
let add = computed({
get(){
console.log("get");
return strs.value+'1234'
},
set(value){
return console.log("set"+value);
}
})
2.watch
/* 监视一项 */
watch(sum,(newValue,oldValue)=>{
console.log(newValue,oldValue);
})
/* immediate:true配置项 */
watch(sum,(newValue,oldValue)=>{
console.log(newValue,oldValue);
},{immediate:true})
/* newValue和oldValue都是数组 */
watch([sum,str],(newValue,oldValue)=>{
console.log(newValue,oldValue);
},{immediate:true})
与Vue2.x中watch配置功能一致
两个小“坑”:
监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)。
监视reactive定义的响应式数据中某个属性时:deep配置有效。
//情况一:监视ref定义的响应式数据
watch(sum,(newValue,oldValue)=>{
console.log('sum变化了',newValue,oldValue)},{immediate:true})
//情况二:监视多个ref定义的响应式数据
watch([sum,msg],(newValue,oldValue)=>{
console.log('sum或msg变化了',newValue,oldValue)
})
//情况三:监视reactive定义的响应式数据
//若watch监视的是reactive定义的响应式数据,则无法正确获得oldValue!
//若watch监视的是reactive定义的响应式数据,则强制开启了深度监视
watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
},{immediate:true,deep:false})
//此处的deep配置不再奏效
//情况四:监视reactive定义的响应式数据中的某个属性
watch(()=>person.job,(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true})
3.watchEffect函数
当在里面使用的变量被修改时调用
4.生命周期钩子

5.自定义hook
将组合API进行封装
复用代码 类似于vue2的mixin
6.Toref和Torefs
创建一个ref数据,其值value指向另一个对象中的某个属性
const name = toRef(person,‘name’);
将响应式对象中的某个属性单独提供给外部使用时
toRef和toRefs作用相同,可以批量创建多个ref对象
4.其他Composition API
1.shallowReactive
只考虑第一层数据的响应式
2.shallowRef
只处理基本基本数据类型的响应式,不进行对象的响应式处理
3.readonly
只读
不允许数据被修改时
4.shallowReadonly
浅只读,只考虑第一层数据
不允许数据被修改时
5.toRaw
转换为原始对象
toRaw:
作用:将一个由reactive生成的响应式对象转为普通对象
使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新
6.markRaw
把…标记为原始
作用:标记一个对象,使其永远不会再成为响应式对象
应用场景:
1.有些值不应被设置为响应式的,例如复杂的第三方类库等
2.当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能
7.customRef
自定义ref
实现防抖效果
<template>
<div>
<input type="text" v-model="keyWord">
<h3>{{keyWord}}</h3>
</div>
</template>
<script lang="ts">
import {ref,customRef} from 'vue';
export default {
name:'Person',
setup() {
function myref(value){
let timer
//传递参数
return customRef((tarck:any,trigger:any):any => {
return {
get(){
console.log(`获取${value}`);
tarck(); //通知vue追踪value的变化
return value;
},
set(newValue):void{
clearTimeout(timer);
timer = setTimeout(()=>{
console.log(`修改${value}`);
value = newValue;
trigger(); //通知vue重新解析模板
},500)
}
}
});
}
let keyWord:any = myref('h');
return {keyWord};
}
}
</script>
<style>
</style>
8.provide,inject
实现祖孙组件通信
provide提供数据
inject使用数据
provide('per',per);
setup(){
let per = inject('per');
return {per};
}
9.响应式数据的判断
isRef
isReactive
isReafonly
isProxy
5.新组件
1.Fragment
减少标签层级,减少内存占用
2.Teleport
将组件html结构移动到指定位置
import {toRefs,provide, reactive,defineAsyncComponent} from 'vue';
const Student = defineAsyncComponent(()=> import('./components/Student.vue'))
<Suspense>
<template #default>
<Student/>
</template>
<template #fallback>
<div>组件加载中...</div>
</template>
</Suspense>