customRef自定义
自定义ref,需要首先到vue里面按需引入;
- 在函数中return自定义ref,传入的参数也是一个带俩形参的箭头函数
- 箭头函数里面又return一个getter方法和一个setter方法
- get和set方法分别用trank和trigger方法分析
<script setup lang="ts">
import { customRef } from 'vue'
function ARef<T>(value: T) {
return customRef((trank, trigger) => {
return {
get() {
trank()
return value
},
set(newVal: T) {
console.log('set');
value = newVal
trigger()
}
}
})
}
</script>
Reactive
Reactive同样也是解决响应式问题,相关规定如下:
- 只能接受一个数组或一个对象作为参数,若传入数组则会被转换为proxy对象
- 调用时无需添加value,如代码中直接obj.name,而使用ref方法那应该写作obj.value.name
<script setup lang="ts">
import { reactive } from 'vue';
const arr = reactive([1, 2, 3]) // 接受数组参数
const obj = reactive({ // 接受对象参数
name: 'helloworld'
})
const changeObj = () => {
console.log(obj.name); // 调用免去了value
}
</script>
在某方法内直接对reactive中对象进行赋值会破坏响应式结构,即不会执行对应的更新!
解决办法:
- push方法向reactive数组内压入属性或者方法(注意这里reactive的参数是一个数组而不是对象!),其中reactive必须显式指定数据类型(针对typescript)
- type设置自定义数据类型后直接赋值(没多少人用,这里省略不介绍了。。。)
<!-- push方法解决响应式破坏问题 -->
<script setup lang="ts">
import { reactive } from 'vue';
let obj = reactive<number[]>([]) // 显式指定数据类型
const addObj = ()=>{
let arr = [1,2,3,4] // 欲插入的数组
obj.push(...arr) // 解构赋值
}
</script>
shallowReactive
定义:仅对第一层具有响应式,不处理深层次对象(和reactive是反着来的)
如下代码,单击按钮触发方法改变深层对象属性后,不会触发渲染更新(即失去了响应式特性)
<script setup lang="ts">
import { shallowReactive } from 'vue';
const sr = shallowReactive({
surface:'hello', // 没有嵌套,表层对象
deep:{
deepname:'hey' // 两层嵌套,深层对象
}
})
const changeDeepen = ()=>{
sr.surface='goodbye' // 可以渲染更新
sr.deep.deepname='say' // 不进行渲染更新
}
</script>
<template>
<div>
<!-- 因为没有渲染更新,按钮名称不会发生改变 -->
<button @click="changeDeepen">{{sr.deep.deepname}}</button>
</div>
</template>