接受一个 getter 函数,并根据 getter 的返回值返回一个不可变的响应式 ref 对象。也就是说,如果我们观察的是
ref或者reactive数据,返回后的数据不能在修改
- <template>
- <div>{{ plusOne }}</div>
- </template>
- <script setup>
- import { computed } from "vue";
-
- // 定义一个计算属性
- const count = ref(1)
- const plusOne = computed(() => count.value + 1)
-
- // 但是注意computed返回的数据是不可变数据
- // plusOne.value++ // 错误
- </script>
如果我们想后面在修改则可以传入 get 和 set 函数的对象可用来创建可写的 ref 对象
- <template>
- <div>{{ plusOne }}</div>
- </template>
- <script setup>
- import { computed, ref } from "vue";
- const count = ref(1)
- const plusOne = computed({
- /**
- * 劫持数据,每次获取的时候,都会自动给数据+1
- * 比如 现在template里面的plusOne就是1000
- * 注意要有返回值,返回的值就是我们拿到的结果
- * 如果说对get不想做操作那么就直接把我们要返回的值返回
- */
- get: () => {
- return 1000
- },
- /**
- * 每次修改的时候数据-1
- * 不需要返回值 这个val就是我们plusOne的值
- * 如果说不想劫持则可以直接默认赋值
- */
- set: val => {
- count.value = val - 1
- }
- })
- plusOne.value += 1
- /**
- * 这个值是1000,以为我们在劫持了他的数据修改
- * 所以我们+1 然后 数据再去件-1,所以相当于没变
- */
- console.log(plusOne.value)
- </script>
为了根据响应式状态自动应用和重新应用副作用,我们可以使用 watchEffect 函数。它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数,简单来说,我们写的函数,会立即执行一次,然后每次里面的数据发生变化后再出发该函数
- <template>
- <div>{{ count }}</div>
- </template>
- <script setup>
- import { watchEffect, ref, reactive } from "vue";
- const count = ref(1)
- const info = reactive({ name: '张三' })
- /**
- * 创建后会立即执行,然后每次里面使用的响应式数据发生改变的时候
- * 注意是响应式数据
- * 该函数会再再次执行
- */
- watchEffect(() => {
- console.log(count.value)
- console.log(info.name)
- })
-
- setTimeout(() => {
- count.value += 1
- }, 100)
-
- setTimeout(() => {
- info.name = '李四'
- }, 2000)
-
- </script>
watch用来监听特定的数据源,并在回调函数中执行。
- <template>
- <div>{{ count }}</div>
- </template>
- <script setup>
- import { watch, ref, reactive } from "vue";
- const count = ref(1)
- const count2 = ref(2)
- const info = reactive({ name: '张三' })
-
- /**
- * 监听原始数据类型变化时,可以直接传入
- * 数据里面可以跟多个值,有一个值变化就会触发这个方法
- * 对应的返回值可以使用数据解构出来
- */
- watch([count, count2], ([newVal, newVal2], [oldVal, oldVal2]) => {
- console.log(newVal, oldVal)
- console.log(newVal2, oldVal2)
- })
-
- setTimeout(() => {
- count.value += 1
- count2.value += 2
- }, 1000)
-
-
- </script>
监听对象类型的数据,并且可以传入第三个参数,是个对象deep 是否深度观察immediate立即执行一次
- <template>
- <div>哈哈哈</div>
- </template>
- <script setup>
- import { watch, ref, reactive } from "vue";
-
- const info = reactive({ name: '张三' })
- const info2 = reactive({ name: '李四' })
-
- /**
- * 观察一个或者多个对象的变化,要使用函数的方式返回那个对象
- * 如果对象中有属性发生变化就会触发方法
- * 注意:watch默认是惰性的,如果观察对象需要手动在第三个参数加{deep: true}
- */
- const stop = watch([() => info, () => info2],
- ([newVal, oldVal], [newVal2, oldVal2]) => {
- console.log(newVal, oldVal)
- console.log(newVal2, oldVal2)
- }, {
- deep: true,
- immediate: true
- })
-
- setTimeout(() => {
- info.name = '王五'
- info2.name = '王五2'
- }, 1000)
-
- // 如果想移除监听则可以拿到watch的返回,并在合适的时候调用它
- stop()
-
- </script>
1、watchEffect不需要指定监听的属性,自动收集依赖;watch需要指定监听的属性
2、watchEffect拿不到旧值;watch可以拿到旧值
3、watchEffect在组件第一次就会收集依赖,然后收集到的依赖发生了变化,回调才会再次执行;watch就不是了。一开始就指定了依赖。