vue3.0 watch
2023-09-10 本文已影响0人
zhudying
watch
- 单个数据监听
<script setup>
import { ref, watch } from 'vue';
const question = ref('')
watch(
question,
(newV, oldV) => {}
)
</script>
- 多个数据监听
<script setup>
import { ref, watch } from 'vue';
const a = ref(1);
const b= ref(2);
// getter 函数
watch(
() => a.value + b.value,
(sum) => {}
)
// 数组形式
watch(
[a, b],
([newA,newB]) => {}
)
</script>
- 监听对象的值
<script setup>
import { reactive, watch } from 'vue';
const obj = reactive({
count: 1
})
watch(
() => obj.count,
(count) => { }
)
</script>
深层侦听器
直接给 watch() 传入一个响应式对象,会隐式地创建一个深层侦听器——该回调函数在所有嵌套的变更时都会被触发:
<script setup>
import { reactive, watch } from 'vue';
const obj = reactive({
count: 1
})
watch(
obj,
(newValue, oldValue) => {
// 注意:`newValue` 此处和 `oldValue` 是相等的
// 因为它们是同一个对象!
}
)
</script>
而在监听 obj.count 时不会创建深层侦听器
<script setup>
import { reactive, watch } from 'vue';
const state= reactive({
obj: {
name: '12'
}
})
watch(
() => state.obj,
(newValue, oldValue) => {
// 注意:当 obj 整体替换时,才会触发,state.obj.name = '4' 不会触发;state.obj = {name: '4' } 触发
}
)
</script>
deep ,强制转成深层侦听器
深度侦听需要遍历被侦听对象中的所有嵌套的属性,当用于大型数据结构时,开销很大。因此请只在必要时才使用它,并且要留意性能。
<script setup>
import { reactive, watch } from 'vue';
const state= reactive({
obj: {
name: '12'
}
})
watch(
() => state.obj,
(newValue, oldValue) => {
// 注意:state.obj.name = '4' 会触发
},
{ deep: true }
)
</script>
watch 默认是懒执行的:仅当数据源变化时,才会执行回调。但在某些场景中,我们希望在创建侦听器时,立即执行一遍回调
我们可以通过传入 immediate: true 选项来强制侦听器的回调立即执行:
<script setup>
import { ref, watch } from 'vue';
const question = ref('')
watch(
question,
(newV, oldV) => {},
{ immediate: true }
)
</script>
watchEffect()
自动跟踪回调的响应式依赖
watchEffect() 可能会比深度侦听器更有效,因为它将只跟踪回调中被使用到的属性,而不是递归地跟踪所有的属性。
watchEffect 仅会在其同步执行期间,才追踪依赖。在使用异步回调时,只有在第一个 await 正常工作前访问到的属性才会被追踪。
<script setup>
import { ref, watchEffect } from 'vue';
let a = ref(1)
let b = ref('')
const sum = (num: any) => {
let res = ''
if (num < 5) {
res = '年龄小于5'
}
return res
}
watchEffect(
() => {
let t = sum(a.value)
b.value = t
// 立即执行,自动追踪 a 的变化
}
)
</script>
flush 回调的触发时机
当你更改了响应式状态,它可能会同时触发 Vue 组件更新和侦听器回调。
默认情况下,用户创建的侦听器回调,都会在 Vue 组件更新之前被调用。这意味着你在侦听器回调中访问的 DOM 将是被 Vue 更新之前的状态。
如果想在侦听器回调中能访问被 Vue 更新之后的 DOM,你需要指明 flush: 'post' 选项
<script setup>
import { watch, watchPostEffect } from 'vue';
watch(source, callback, {
flush: 'post'
})
// 或
watchPostEffect(() => {
/* 在 Vue 更新后执行 */
})
</script>
停止侦听器
同步: 在 setup() 或 <script setup> 中用同步语句创建的侦听器,会自动绑定到宿主组件实例上,并且会在宿主组件卸载时自动停止。因此,在大多数情况下,你无需关心怎么停止一个侦听器。
异步: 如果用异步回调创建一个侦听器,那么它不会绑定到当前组件上,你必须手动停止它
<script setup>
import { watchEffect } from 'vue'
// 它会自动停止
watchEffect(() => {})
// ...这个则不会!
setTimeout(() => {
watchEffect(() => {})
}, 100)
</script>
要手动停止一个侦听器,请调用 watch 或 watchEffect 返回的函数:
const unwatch = watchEffect(() => {})
// ...当该侦听器不再需要时
unwatch()