vue3|vue3.0常用的composition API

一、setup函数 setup:一般返回一个对象,对象的key可以直接使用(也可以返回一个渲染函数)
二、ref函数 创建一个响应值:ref(“张三”),ref({ name:“张三” }),返回一个RefImpl对象(引用实现的实例化对象,简称引用对象,也叫ref对象)
操作基础类型的响应值:ref(“张三”).value,ref(“张三”).value = https://www.it610.com/article/“李四”
操作引用类型的响应值:ref({ name:“张三” }).value.name,ref({ name:“张三” }).value.name = “李四”
重点:ref函数返回的是ref对象,当创建的是基础类型的响应式是使用的是object.defineproperty的get与set方法进行数据劫持;当创建的是引用类型时使用的是ES6里面的 Proxy对象 进行代理实现的(实际上是求助了reactive函数)
三、reactive函数 作用:定义一个对象类型的响应式数据(基础类型不能用它)
创建一个响应值:const 代理对象 = reactive(源对象),返回一个代理对象(Proxy的实例化对象,简称Proxy对象)
操作响应值:reactive({ name:“张三” }).name,reactive({ name:“张三” }).name = “李四”
四、回忆vue2 的响应式 【vue3|vue3.0常用的composition API】1. 实现原理

  • 对象类型:进行递归遍历对象的属性进行object.defineproperty的数据劫持
  • 数组类型:通过重写更新数组的一系列方法来进行实现拦截。(对数组的变更方法进行包裹)
2. 存在问题
  • 新增,删除属性时,界面不会更新
  • 直接通过下标修改数组,界面不会更新
  • 得采用 s e t , set, set,delete,splice等方式进行修改
四、了解vue3 的响应式 实现原理:
  • 通过Proxy(代理):拦截对象中任意属性的变化
  • 通过Reflect(反射):对源对象的属性进行操作(好处是Reflect不会直接抛错)
const data = https://www.it610.com/article/{ name:"haonan" } const proxy = new Proxy(data, { //拦截读取属性 get(target,prop){ return Reflect.get(target,prop) }, //拦截修改和新增属性 set(target,prop,value){ return Reflect.set(target,prop,value) }, //拦截删除属性 defineProperty(target,prop){ return Reflect.defineProperty(target,prop) }, })proxy.name = "henry"

五、setup的两个注意点 setup执行的时机:在beforeCreate之前执行一次,this是undefined
setup的参数:
  • props:值为Proxy对象,包含 组件外部传递过来,且组件内部声明接收了的属性
  • context:上下文对象
attrs:值为对象,包含 组件外部传递过来,但没有在props内部声明的属性,相当于vue2中的this.$attrs
slots:收到的插槽内容,相当于this.$slots。(vue3中得写成v-slot:,不要写成solt=""
emit:分发自定义事件的函数,相当于this.$emit
六、计算属性与监视 1.computed函数
import { computed,reactive } from "vue"; setup() { const user = reactive({ firstName: "张", lastName: "三", }); //简写 user.fullName = computed(() => { return user.firstName + "-" + user.lastName; }); //完整写法 user.fullName = computed({ set(value){ const arr = value.split('-') user.firstName = arr[0] user.lastName = arr[1] }, get(){ return user.firstName + "-" + user.lastName; } }); return { user, }; },

2.watch函数 需要注意:
  • 监听reactive定义的响应式数据时:oldValue无法正确获取、且是强制的深度监听(deep配置失效)
  • 监听reactive定义的响应式数据中的某个属性时:不会深度监听,deep配置依旧有效
  • 当监听的是reactive定义的响应式数据中的某个属性时,需要使用 ()=> 包裹监听的数据属性
const user = reactive({ name:"henry", job:{ c:'1', a:{ b:222 } } }) watch(user,(newval,oldval)=>{ console.log('user',newval,oldval) },{ immediate:true,//有效 deep:false //无效,当监听的对象是Proxy对象时,强制开启深度监听,且无法正确获取oldVal }) watch([()=>user.name,()=>user.job.a.b],(newval,oldval)=>{//多个监听时,可以用数组的形式 console.log('名称和薪资有更新',newval,oldval) }) watch(()=>user.name,(newval,oldval)=>{//当你监听的是对象的属性,并且是一个基础类型时,一定得用'()=>'的方式监听 console.log('名称有更新',newval,oldval) }) watch(()=>user.job,(newval,oldval)=>{//当你监听的是对象的属性,并且该属性的值是一个对象时,可用可不用'()=>'的方式监听,此时不会开启深度监听,需要配置deep才能开启深度监听 console.log('job有更新',newval,oldval) },{ deep:true })

当使用ref创建对象类型的数据时,由于ref内部是求助了reactive函数,所以需要监听.value或者开启deep,此时依旧无法正确获取oldVal
//方式一: watch(user,(newval,oldval)=>{ console.log('user',newval,oldval) },{ deep:true }) //方式二: watch(user.value,(newval,oldval)=>{ console.log('user',newval,oldval) })

3.watchEffect函数 作用:监听函数内用到所有属性
watchEffect(()=>{ user.income = user.income1 + user.income2 user.expend = user.expend1 + user.expend2 user.total = user.income - user.expend console.log('watchEffect user++++',user) })

watchEffect 有点像 computed:
  • computed注重结果,需要写返回值
  • watchEffect注重过程,不用写返回值
七、生命周期 1.改名 beforeDestroy(不起作用了) => beforeUnmount
destroyed(不起作用了) => unmounted
2.composition API形式的生命周期 beforeCreate => setup
created => setup
beforeMount => onBeforeMount
mounted => onMounted
beforeUpdate => onBeforeUpdate
updated => onUpdated
beforeUnmount => onBeforeUnmount
unmounted => onUnmounted
3.composition API 和 生命周期配置 的优先级 尽管开发时,不太可能即用composition API和生命周期配置,但需了解 composition API 比 生命周期配置先触发
4.el vue2时,即使你没有配置el,beforeCreate和created也会触发;
而vue3中,如果你没有配置el,则不会触发beforeCreate和created
八、自定义hook函数 本质是一个函数,把setup函数中使用的composition API进行了封装
类似于vue2中的mixin
优势:复用代码,让setup中的逻辑更清楚易懂
PS:尽量使用use***命名,例如usePoint
九、toRef 创建一个ref对象,其value值指向另一个响应式对象中的某个属性
const name = toRef(user,'name') const c = toRef(user.job.a,'c')

可以用来将响应式对象中的某个属性单独提供给外部使用
如果要创建扩展一个响应式对象的所有属性时,可以用toRefs
setup() { const user = reactive({ name:"henry", age:25 }) return { ...toRefs(user) }; }

    推荐阅读