1.自定义hook函数
2.toRef和toRefs
3.shallowRef和shallowReactive
4.readonly和shallowReadonly
5.toRaw和markRaw
6.customref
一.自定义hook函数
① 本质是一个函数,把setup函数中使用的Composition API 进行了封装,类似于vue2.x中的mixin
自定义hook函数可以进行代码复用,让setup中的逻辑更清晰
② 代码实现
(1)新建hooks
(2) 将相关功能和接口写入
usePoint.js
import { reactive, onMounted, onBeforeUnmount } from "vue"
export default function () {
let point = reactive({
x: 0,
y: 0
})
function savePoint (event) {
console.log(event.pageX, event.pageY)
point.x = event.pageX
point.y = event.pageY
}
onMounted(() => {
window.addEventListener('click', savePoint)
})
onBeforeUnmount(() => {
window.removeEventListener('click', savePoint)
})
return point
}
(3)引入和使用
(4)代码汇总
Demo.vue
<template>
<h2>当前求和为:{{ sum }}</h2>
<button @click="sum++">点我+1</button>
<hr />
<h2>当前点击时鼠标的坐标为:x : {{ point.x }} y:{{ point.y }}</h2>
</template>
<script>
import usePoint from '../hooks/usePoint'
import { reactive, ref, onMounted, onBeforeUnmount } from 'vue'
export default {
name: 'Demo',
// 数据
setup () {
let sum = ref(0)
let point = usePoint()
return {
sum,
point
}
},
}
</script>
<style>
</style>
Test.vue
<template>
<h2>我是Test组件</h2>
<h2>当前点击时鼠标的坐标为:x : {{ point.x }} y:{{ point.y }}</h2>
</template>
<script>
import usePoint from '../hooks/usePoint'
export default {
name: 'Test',
setup () {
const point = usePoint()
return { point }
}
}
</script>
二. toRef和toRefs
① 作用:创建一个ref对象,其value值指向另一个对象中的某个属性
② 应用: 要将响应式对象中的某个属性单独提供给外部使用,不想丢失响应式
toRef与toRefs功能一致,toRefs可以批量创建多个ref对象,处理这个对象中的所有属性
③ 代码
<template>
<h4>{{ person }}</h4>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
<h2>薪资:{{ job.j1.salary }}</h2>
<button @click="name += '~'">修改姓名</button>
<button @click="age++">增长年龄</button>
<button @click="job.j1.salary++">涨薪</button>
</template>
<script>
import { reactive, ref, toRef, toRefs } from 'vue'
export default {
name: 'Demo',
// 数据
setup () {
let person = reactive({
name: '张三',
age: 18,
job: {
j1: {
salary: 20
}
}
})
return {
person,
// name: toRef(person, 'name'),
// age: toRef(person, 'age'),
// salary: toRef(person.job.j1, 'salary')
...toRefs(person)
}
}
}
</script>
<style>
</style>
三.shallowRef和shallowReactive
引入:import { shallowReactive, shallowRef } from 'vue'
① shallowReactive:只处理对象最外层属性的响应式(浅响应式)
② shallowRef: 只处理基本数据类型的响应式,不进行对象的响应式处理
③ 使用场景:
- 如果有一个对象数据,结构比较深,但变化只是外层属性变化的时候使用shallowReactive
- 如果有一个对象数据,后续功能不会修改对象中的属性,而是生成新的对象替换 => shallowRef
四.readonly和shallowReadonly
应用场景:不希望数据被修改
① readonly: 让一个响应式数据变成只读的(深只读)
② shallowReadonly:只限制对象中的第一层数据
对ref的对象同样有用
五.toRaw和markRaw
① toRaw
- 作用:将一个由reactive生成的响应式对象转为普通对象
- 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新
② markRaw
- 作用:标记一个对象,使其永远不会再成为响应式对象
- 应用场景
1.有些值不应该被设置为响应式的,例如复杂的第三方类库等
2.当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能
操作数据,数据确实发生变化了,但是界面不会发生变化,没有响应式
六.customref
作用:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显式控制
实现防抖效果代码实现:
<template>
<input type="text" v-model="keyWord" />
<h3>{{ keyWord }}</h3>
</template>
<script>
import { ref, customRef } from 'vue'
import Demo from './components/Demo.vue'
export default {
name: 'App',
setup () {
// 自定义ref
function myRef (value, delay) {
let timer
return customRef((track, trigger) => {
return {
get () {
track() // 通知Vue追踪value的变化
console.log('有人从myRef中读取数据了')
return value
},
set (newValue) {
console.log('有人把myRef中的数据改了')
clearTimeout(timer)
timer = setTimeout(() => {
value = newValue
trigger() // 通知vue去重新解析模板
}, delay)
}
}
})
}
let keyWord = myRef('hello', 500)
return { keyWord }
}
}
</script>