customRef 自定义响应式
防抖,要求100ms后再更新
useDebounce.js
import {customRef} from 'vue'
export default function(value,delay = 300){
let timer = null
return customRef((track,trigger)=>{
return {
get(){
track();
return value
},
set(newValue){
clearTimeout(timer)
timer = setTimeout(()=>{
value = newValue;
trigger();
},delay)
}
}
})
}
组件内使用
import debounceRef from './useDebounce.js'
export default{
setup(){
const message = debounceRef("hello world")
return{
message
}
}
}
coumputed 计算属性
当我们的某些属性是依赖其他数据变量时,可以使用计算属性来动态更新
第一种写法: 参数为一个函数,返回的是不变的ref对象(自身不可变,会跟着依赖属性变化更新)
const fullName = computed(()=>{
return firstName.vlaue + ' ' + lastName.value
})
第二种写法:参数为一个对象,返回的是可变的(可读写)ref对象(自身可以修改,手动更新依赖属性)
const fullName = computed({
get(){
return firstName.value + ' ' + lastName.value
},
set(newValue){
const names = newValue.split(' ')
firstName.value = names[0]
lastname.value = names[1]
}
})
watchEffect
自动收集响应式数据的依赖
1.watchEffect 传入的函数会被默认立即执行,并且在执行过程中会收集依赖(函数里面有用到的变量都会被收集到)
2.只有收集的依赖发生变化时,watchEffect 传入的函数才会执行
const name = ref('tomato')
const age = ref(18)
watchEffect(()=>{
console.log(name.value,age.value)
})
watchEffect 停止监听
调用watchEffect函数的返回值可以停止监听
const stopWatch = watchEffect(()=>{....})
const changeAge = () =>{
age.value++
if(age.value>20){
stopWatch()
}
}
watchEffect 清除副作用
- 什么是清除副作用?
- 比如在开发中我们需要侦听函数中执行网络请求,但是网络请求还没有达到的时候,我们停止了侦听或者侦听器侦听函数再次被执行了
- 那么上一次的网络请求应该被取消掉,这个时候就可以清除上一次的副作用
- 给watchEffect 传入的函数被回调,可以获取到一个参数: onInvalidate
- 当副作用即将重新执行或者侦听器被停止时就会执行该函数传入的回调函数
const stopWatch = watchEffect((onInvalidate)=>{
const timer = setTimeout(()=>{
...
//2s后执行
},2000)
onInvalidate(()=>{clearTimeout(timer)})
})
watchEffect 的执行时机
默认情况下,组件的更新会在副作用函数(onInvalidate)执行之前,如果想等到挂载完再执行 ,传入第二个参数watchEffect(()=>{},{flush:“post”})
watch
watch 默认情况下是惰性的,只有当被侦听的数据源发生变化时才会执行回调
watch侦听单个数据源
1.一个getter函数,但是该函数必须引用可响应式的对象(reactive || ref)
const info = reactive({
name:"tomato",
age:18
})
2.直接写入一个可响应式的对象,reactive || ref
- 情况一:
watch(info,(newValue,oldValue)=>{
...
newValue,oldValue 本身都是reactive对象
})
如果希望newValue,oldValue是一个普通对象
watch(()=>{return{...info}},(newValue,oldValue)=>{
})
- 情况二 ref对象获取newValue 和oldValue是value值的本身
const name = ref("tomato")
watch(name,(newValue,oldValue)=>{})
watch侦听多个数据源
const info = reactive({name:"tomato",age:18})
const name = ref("lili")
// 数组,() 执行函数
watch([()=>({...info}),name],([newInfo,newName],[oldInfo,oldName])=>{
// 拿到的都是普通的对象和变量
})
watch侦听数组
const names = reactive(["lili","lucy","tomato"])
const info = reactive({name:"tomato",age:18})
watch(()=>[...names],(newValue,oldValue)=>{
})
watch的选项
深度监听&立即执行 deep:true,immediate:true
deep:true. 第一个参数这样的写法必须加deep才能深度监听(watch(()=>({…info})),()=>{},{})
immediate:true. 立即执行,第一次是否执行,默认第一次不执行
const info = reactive({
name:"tomato",
age:18,
friend:{
name:"fc"
}
})
watch(()=>info,(newValue,oldValue)=>{},{deep:true,immediate:true})
watch 与 watchEffect比较
- watch 懒执行副作用(第一次不会执行)
- 更具体的说明当哪些状态发生变化时,触发侦听器的执行
- 访问侦听状态变化前后的值
setup中使用ref
定义一个ref对象,绑定到元素或者组件的ref属性上即可
<template>
<h2 ref='title'>标题</h2>
</template>
<script>
import {ref} from 'vue'
export default{
setup(){
const title = ref(null)
return{
title
}
}
}
</script>
provide 函数 && inject函数
provide 提供数据,inject获取数据
用法
祖先.vue
setup(){
const name = ref('tomato')
let counter = ref(100)
const info = {
name:"tomato"
}
const changeInfo = () =>{
info.name = "fc"
}
provide("name",readonly(name))
provide("counter",readonly(counter)) // 传过去只读的数据
}
后代.vue
setup(){
const name = inject('name')
const counter = inject('counter')
}