【vue3】关于watch与computed的用法看这个就ok

简介: watch()与computed的使用

【前言】vue2当中有这两个技能,那么vue3中的watch与computed是怎么用呢?

⭐一、watch

1.检测reactive内部数据

<template>
  <p>{{ obj.hobby.eat }}</p>
  <button @click="obj.hobby.eat = '面条'">click</button>
</template>
<script>
  import { watch, reactive } from 'vue'
  export default {
      name: 'App',
      setup() {
          const obj = reactive({
              name: 'ifer',
              hobby: {
                  eat: '西瓜',
              },
          })
          watch(obj, (newValue, oldValue) => {
              // 注意1:监听对象的时候,新旧值是相等的
              // 注意2:强制开启深度监听,配置无效
              console.log('触发监听');
              console.log(newValue === oldValue) // true
          })
          return { obj }
      },
  }
</script>

注意点:对 reactive 自身的修改则不会触发监听。

<template>
    <p>{{ obj.hobby.eat }}</p>
    <button @click="obj.hobby = { eat: '面条' }">click</button>
</template>
<script>
    import { watch, reactive } from 'vue'
    export default {
        name: 'App',
        setup() {
            const obj = reactive({
                name: 'ifer',
                hobby: {
                    eat: '西瓜',
                },
            })
            watch(obj.hobby, (newValue, oldValue) => {
                // obj.hobby = { eat: '面条' }
                console.log('对 reactive 自身的修改不会触发监听')
            })
            return { obj }
        },
    }
</script>

77dc636772cc43b3a14a21365b53a7dd.png一定得注意不能修改reactive本身,修改本身不触发

2.监听 ref 数据

2.1监听一个 ref 数据

<template>
  <p>{{ age }}</p>
  <button @click="age++">click</button>
</template>
<script>
  import { watch, ref } from 'vue'
  export default {
      name: 'App',
      setup() {
          const age = ref(18)
          // 监听 ref 数据 age,会触发后面的回调,不需要 .value
          watch(age, (newValue, oldValue) => {
              console.log(newValue, oldValue)
          })
          return { age }
      },
  }
</script>

2.2监听多个 ref 数据

可以通过数组的形式,同时监听 age 和 num 的变化。

<template>
    <p>age: {{ age }} num: {{ num }}</p>
    <button @click="handleClick">click</button>
</template>
<script>
    import { watch, ref } from 'vue'
    export default {
        name: 'App',
        setup() {
            const age = ref(18)
            const num = ref(0)
            const handleClick = () => {
                age.value++
                num.value++
            }
            // 数组里面是 ref 数据
            watch([age, num], (newValue, oldValue) => {
                console.log(newValue, oldValue)
            })
            return { age, num, handleClick }
        },
    }
</script>

20b88531d94a43c3a26cabb82f00a6b7.png

立即触发监听属性:

{
                    immediate: true,
                }
<template>
    <p>{{ age }}</p>
    <button @click="handleClick">click</button>
</template>
<script>
    import { watch, ref } from 'vue'
    export default {
        name: 'App',
        setup() {
            const age = ref(18)
            const handleClick = () => {
                age.value++
            }
            watch(
                age,
                (newValue, oldValue) => {
                    console.log(newValue, oldValue) // 18 undefined
                },
                {
                    immediate: true,
                }
            )
            return { age, handleClick }
        },
    }
</script>

16fe04095b8447729f76fa984732d40c.png

开启深度监听 ref 数据

📝 问题:修改 ref 对象里面的数据并不会触发监听,说明 ref 并不是默认开启 deep 的。见下
<template>
    <p>{{ obj.hobby.eat }}</p>
    <button @click="obj.hobby.eat = '面条'">修改 obj.hobby.eat</button>
</template>
<script>
    import { watch, ref } from 'vue'
    export default {
        name: 'App',
        setup() {
            const obj = ref({
                hobby: {
                    eat: '西瓜',
                },
            })
            // 注意:ref 监听对象,默认监听的是这个对象地址的变化
            watch(obj, (newValue, oldValue) => {
                console.log(newValue === oldValue)
            })
            return { obj }
        },
    }
</script>

afa56939f21245aeb1be206422e39dd0.png面对这样的没有触发watch我们解决办法有三个:

解决 1:当然直接修改整个对象的话肯定是会被监听到的(注意模板中对 obj 的修改,相当于修改的是 obj.value)。

-`

{{ obj.hobby.eat }}

`

a159d979aa3e4bdab3ed3d8cdc7dd43b.png

解决 2:开启深度监听 ref 数据。

watch(
    obj,
    (newValue, oldValue) => {
        console.log(newValue, oldValue)
        console.log(newValue === oldValue)
    },
    {
        deep: true,
    }
)

就加上一句话,故此没有截图

解决 3:还可以通过监听 ref.value 来实现同样的效果。

因为 ref 内部如果包裹对象的话,其实还是借助 reactive 实现的,可以通过 isReactive 方法来证明。

<template>
    <p>{{ obj.hobby.eat }}</p>
    <button @click="obj.hobby.eat = '面条'">修改 obj</button>
</template>
<script>
    import { watch, ref } from 'vue'
    export default {
        name: 'App',
        setup() {
            const obj = ref({
                hobby: {
                    eat: '西瓜',
                },
            })
            watch(obj.value, (newValue, oldValue) => {
                console.log(newValue, oldValue)
                console.log(newValue === oldValue)
            })
            return { obj }
        },
    }
</script>

fce7f52ef5394efaa793901b97d81e11.png

监听普通数据

监听响应式对象中的某一个普通属性值,要通过函数返回的方式进行(如果返回的是对象/响应式对象,修改内部的数据需要开启深度监听)。

<template>
    <p>{{ obj.hobby.eat }}</p>
    <button @click="obj.hobby.eat = '面条'">修改 obj</button>
</template>
<script>
    import { watch, reactive } from 'vue'
    export default {
        name: 'App',
        setup() {
            const obj = reactive({
                hobby: {
                    eat: '西瓜',
                },
            })
            // 把 obj.hobby 作为普通值去进行监听,只能监听到 obj.hobby 自身的变化
            /* watch(
      () => obj.hobby,
      (newValue, oldValue) => {
        console.log(newValue, oldValue)
        console.log(newValue === oldValue)
      }
    ) */
            // 如果开启了深度监听,则能监听到 obj.hobby 和内部数据的所有变化
            /* watch(
      () => obj.hobby,
      (newValue, oldValue) => {
        console.log(newValue, oldValue)
        console.log(newValue === oldValue)
      },
      {
        deep: true,
      }
    ) */
            // 能监听影响到 obj.hobby.eat 变化的操作,例如 obj.hobby = { eat: '面条' } 或 obj.hobby.eat = '面条',如果是 reactive 直接对 obj 的修改则不会被监听到(ref 可以)
            watch(
                () => obj.hobby.eat,
                (newValue, oldValue) => {
                    console.log(newValue, oldValue)
                    console.log(newValue === oldValue)
                }
            )
            return { obj }
        },
    }
</script>

⭐二、computed

作用:computed 函数用来定义计算属性,上述的基础概念都是同vue2一样的,关于vue2中这两个知识点的定义大家可以移步:【vue2】计算与侦听的用法。

<template>
  <p>firstName: {{ person.firstName }}</p>
  <p>lastName: {{ person.lastName }}</p>
  <input type="text" v-model="person.fullName" />
</template>
<script>
  import { computed, reactive } from 'vue'
  export default {
      name: 'App',
      setup() {
          const person = reactive({
              firstName: '初',
              lastName: '映',
          })
          // 也可以传入对象,目前和上面等价
          person.fullName = computed({
              get() {
                  return person.firstName + '*' + person.lastName
              },
              set(value) {
                console.log(value,'value');//为上述get的返回值
                  const newArr = value.split('*')
                  person.firstName = newArr[0]
                  person.lastName = newArr[1]
              },
          })
          return {
              person,
          }
      },
  }
</script>

5c0904ef29e448a9b2cc5ab6ad7e065d.gif

相关文章
|
23天前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
126 64
|
23天前
|
JavaScript 前端开发 API
Vue 3 中 v-model 与 Vue 2 中 v-model 的区别是什么?
总的来说,Vue 3 中的 `v-model` 在灵活性、与组合式 API 的结合、对自定义组件的支持等方面都有了明显的提升和改进,使其更适应现代前端开发的需求和趋势。但需要注意的是,在迁移过程中可能需要对一些代码进行调整和适配。
103 60
|
23天前
|
前端开发 JavaScript 测试技术
Vue3中v-model在处理自定义组件双向数据绑定时,如何避免循环引用?
Web 组件化是一种有效的开发方法,可以提高项目的质量、效率和可维护性。在实际项目中,要结合项目的具体情况,合理应用 Web 组件化的理念和技术,实现项目的成功实施和交付。通过不断地探索和实践,将 Web 组件化的优势充分发挥出来,为前端开发领域的发展做出贡献。
28 8
|
22天前
|
存储 JavaScript 数据管理
除了provide/inject,Vue3中还有哪些方式可以避免v-model的循环引用?
需要注意的是,在实际开发中,应根据具体的项目需求和组件结构来选择合适的方式来避免`v-model`的循环引用。同时,要综合考虑代码的可读性、可维护性和性能等因素,以确保系统的稳定和高效运行。
22 1
|
22天前
|
JavaScript
Vue3中使用provide/inject来避免v-model的循环引用
`provide`和`inject`是 Vue 3 中非常有用的特性,在处理一些复杂的组件间通信问题时,可以提供一种灵活的解决方案。通过合理使用它们,可以帮助我们更好地避免`v-model`的循环引用问题,提高代码的质量和可维护性。
32 1
|
23天前
|
JavaScript
在 Vue 3 中,如何使用 v-model 来处理自定义组件的双向数据绑定?
需要注意的是,在实际开发中,根据具体的业务需求和组件设计,可能需要对上述步骤进行适当的调整和优化,以确保双向数据绑定的正确性和稳定性。同时,深入理解 Vue 3 的响应式机制和组件通信原理,将有助于更好地运用 `v-model` 实现自定义组件的双向数据绑定。
|
26天前
|
JavaScript 前端开发 API
从Vue 2到Vue 3的演进
从Vue 2到Vue 3的演进
39 0
|
7月前
|
JavaScript API
【vue实战项目】通用管理系统:api封装、404页
【vue实战项目】通用管理系统:api封装、404页
78 3
|
7月前
|
人工智能 JavaScript 前端开发
毕设项目-基于Springboot和Vue实现蛋糕商城系统(三)
毕设项目-基于Springboot和Vue实现蛋糕商城系统
|
7月前
|
JavaScript Java 关系型数据库
毕设项目-基于Springboot和Vue实现蛋糕商城系统(一)
毕设项目-基于Springboot和Vue实现蛋糕商城系统
192 0