computed
- 接受一个 getter 函数,并根据 getter 的返回值返回一个不可变的响应式
ref对象。
const count = ref(1)
const plusOne = computed(() => count.value + 1) // 在computed里只有getter函数,就是一个有返回值的函数,
//这样这个值就不能直接修改否则会报错,但是它仍然会跟随count的改变而改变。
console.log(plusOne.value) // 2
plusOne.value++ // 错误
- 或者,接受一个具有
get和set函数的对象,用来创建可写的 ref 对象。
const count = ref(1)
const plusOne = computed({
get: () => count.value + 1,
set: val => {
count.value = val - 1
}
})
plusOne.value = 1 // 赋值会回调set函数,修改count
console.log(count.value) // 0
watchEffect
立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。
let numbers = ref(0)
const stop = watchEffect(()=>{
console.log(numbers.value); // 开始会打印0,100ms之后打印1
})
setTimeout(()=>{
numbers.value ++
},100)
在一些情况下,也可以显式调用返回值以停止侦听:
添加这里的代码到上面就可以了,可以把上面的setTimeout改为setInterval,就会发现在1000ms之后就不会在打
印值。
setTimeout(()=>{
stop()
},1000)
这里需要注意,当一个用户定义的副作用函数进入队列时,默认情况下,会在所有的组件 update前执行:
// 在下面的代码中会发现,dom元素打印为null,获取不到dom元素,这是因为它的执行时机会早于dom的更新。并不能获取带dom,
<div class="numberbox">
numbers:{{numbers}}
</div>
let numbers = ref(0)
const stop = watchEffect(()=>
{
console.log(document.querySelector('.numberbox')); // 这里会打印null,
console.log(numbers.value);
}
)
解决办法,1.如果异步更新了numbers的值,就会发现可以获取到dom了,但是在进入时让然没有获取到,也可以添加
如果需要在组件更新后重新运行侦听器副作用,我们可以传递带有 flush选项的附加 options 对象 (默认为 'pre'):
flush:有三个值,默认pre,会早于dom更新。post会晚于dom更新。sync,将强制效果始终同步触发。
3.2也可以使用watchPostEffect 和 watchSyncEffect
const stop = watchEffect(()=>
{
console.log(document.querySelector('.numberbox')); // 这样就可以获取到了。
console.log(numbers.value);
},
{
flush: 'post'
})
watch
watch 需要侦听特定的数据源,并在回调函数中执行副作用。默认情况下,它也是惰性的,即只有当被侦听的源发生变化时才执行回调。
watch 和 watchEffect 的区别
- 懒执行副作用;watch监听的数据发生改变时,才会触发。watchEffect是定义了就会默认执行
- 更具体地说明什么状态应该触发侦听器重新运行;
- 访问侦听状态变化前后的值。
侦听单个数据源
侦听器数据源可以是返回值的 getter 函数,也可以直接是 ref:
let watchnum = ref(0)
watch(
watchnum,
(count,precount)=>{
console.log(count,precount);
}
)
侦听多个数据源
可以使用数组同时侦听多个源:
const firstName = ref('')
const lastName = ref('')
watch([firstName, lastName], (newValues, prevValues) => {
console.log(newValues, prevValues)
})
firstName.value = 'John'
lastName.value = 'Smith' logs: ["John", "Smith"] ["", ""]
注意:如果你在同一个函数里同时改变这些被侦听的来源,侦听器仍只会执行一次。如果是多个同步更改只会触发一次侦听器。上面的代码修改来两次监听数据,但是可以看到它只会触发一次监听。如果想要改变这样的监听,可以进行异步操作来对数据进行修改,也可参口上面的watchEffect的使用,传入第三个参数去修改回调时机。