信息发布→ 登录 注册 退出

Vue3中的 computed,watch,watchEffect的使用方法

发布时间:2026-01-11

点击量:
目录
  • 一、computed
  • 二、watch
    • vu2 的写法
    • Vue3 中这样写
  • 三、watchEffect

    一、computed

    <template>
      姓:<input v-model="person.firstName"><br/><br/>
      名:<input  v-model="person.lastName"><br/><br/>
      <span>全名:{{person.fullname}}</span><br/><br/>
      <span>全名:<input v-model="person.fullname"></span>
    </template>
    
    <script>
    import {reactive,computed} from 'vue'
    export default {
      name: 'HelloWorld',
      setup(){
        let person = reactive({
          firstName:"张",
          lastName:"三"
        })
        //computed简写形式,没考虑修改
        /*person.fullname = computed(()=>{
          return person.firstName+"-"+person.lastName;
        })*/
        person.fullname = computed({
          get(){
            return person.firstName+"-"+person.lastName;
          },
          set(value){
            const nameArr = value.split('-');
            person.firstName = nameArr[0];
            person.lastName = nameArr[1];
          }
        })
        return{
          person,
        }
      }
    }
    </script>

    二、watch

    • 1、与 Vue2.x 中 watch 配置功能一致
    • 2、两个小"坑":
      • 监视 reactive 定义的响应式数据时: oldValue 无法正确获取、强制开启了深度监视(deep配置失效)
      • 监视 reactive 定义的响应式数据中某个属性时:deep 配置有效

    我们仍然做之前求和的案例:

    vu2 的写法

    <template>
      <h2>当前求和为:{{ sum }}</h2>
      <button @click="sum++">点我sum++</button>
    </template>
    
    <script>
    import {ref} from 'vue'
    
    export default {
      name: 'Demo',
      watch: {
        /*sum(oldValue,newValue){
          console.log("sum发生了变化",oldValue,newValue);
        }*/
        sum: {
          immediate: true,
          deep:true,
          handler(newValue,oldValue) {
            console.log("sum发生了变化", newValue, oldValue);
          }
        }
      },
      setup() {
        let sum = ref(0);
    
        return {
          sum,
        }
      }
    }
    </script>

    Vue3 中这样写

    1、情况一:监视ref所定义的一个响应式数据

    <template>
      <h2>当前求和为:{{ sum }}</h2>
      <button @click="sum++">点我sum++</button>>
    </template>
    <script>
    import {ref, watch} from 'vue'
    export default {
      name: 'Demo',
      setup() {
        let sum = ref(0);
        let msg = ref("你好啊");
        //情况一:监视ref所定义的一个响应式数据
        watch(sum, (newValue, oldValue) => {
          console.log("sum发生了变化", newValue, oldValue);
        })
    
        return {
          sum
        }
      }
    }
    </script>

    watch 还可以传一个配置项,把 immediate 等配置传进去:

    watch(sum, (newValue, oldValue) => {
          console.log("sum发生了变化", newValue, oldValue);
        },{immediate:true})

    2、情况二:当有多个信息需要同时监视时

    <template>
      <h2>当前求和为:{{ sum }}</h2>
      <button @click="sum++">点我sum++</button>
      <hr/>
      <h2>信息为:{{ msg }}</h2>
      <button @click="msg+='!'">点我sum++</button>
    </template>
    <script>
    import {ref, watch} from 'vue'
    export default {
      name: 'Demo',
      setup() {
        let sum = ref(0);
        let msg = ref("你好啊");
    
        //情况二:监视ref所定义的多个响应式数据
        watch([sum,msg],(newValue, oldValue) => {
          console.log("sum发生了变化", newValue, oldValue);
        })
    
        return {
          sum,
          msg
        }
      }
    }
    </script>

    3、情况三:监视reactive所定义的一个响应式数据

    <template>
      <h2>姓名:{{ person.name }}</h2>
      <h2>年龄:{{ person.age }}</h2>
      <h2>薪资:{{ person.job.j1.salary }}K</h2>
      <button @click="person.name+='~'">修改姓名</button>
      <button @click="person.age++">修改年龄</button>
      <button @click="person.job.j1.salary++">涨薪</button>
    </template>
    <script>
    import {reactive, watch} from 'vue'
    
    export default {
      name: 'Demo',
      setup() {
        let person = reactive({
          name: "张三",
          age: 18,
          job:{
            j1:{
              salary:20
            }
          }
        })
        //情况三:监视reactive所定义的一个响应式数据全部属性
        // 1\注意:无法正确获取oldvalue
        // 2\注意:强制开启了深度监视(deep配置无效)
        watch(person, (newValue, oldValue) => {
          console.log("person发生了变化", newValue, oldValue);
        })
    
        return {
          person
        }
      }
    }
    </script>

    4、情况四:监视reactive所定义的一个响应式数据某个属性

    //情况四:监视reactive所定义的一个响应式数据某个属性
        watch(()=>person.name, (newValue, oldValue) => {
          console.log("person的name发生了变化", newValue, oldValue);
        })

    5、情况五:监视 reactive 所定义的一个响应式数据某些属性

    //情况五:监视reactive所定义的一个响应式数据某个属性
        watch([()=>person.name,()=>person.age], (newValue, oldValue) => {
          console.log("person的name或age发生了变化", newValue, oldValue);
        })

     6、特殊情况,监视对象中的某个对象属性,要开始deep:true

    watch(()=>person.job, (newValue, oldValue) => {
    	console.log("person的job发生了变化", newValue, oldValue);
    },{deep:true})//由于监视的是reactive对象中的某个属性,deep奏效

    7、监视 ref 定义的对象响应数据,需要.value或deep:true

    	let person = ref({
          name: "张三",
          age: 18,
          job:{
            j1:{
              salary:20
            }
          }
        })
        watch(person.value, (newValue, oldValue) => {
          console.log("person的value发生了变化", newValue, oldValue);
        })
        或
        watch(person, (newValue, oldValue) => {
          console.log("person的value发生了变化", newValue, oldValue);
        },{deep:true})

    三、watchEffect

    watch 的套路是:既要指明监视的属性,也要指明监视的回调

    watchEffect 的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性

    watchEffect有点像computed

    。但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值

    。而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值

    //watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调
    watchEffect(()=>{
    	const xl = sum.value
    	const x2 = person.age
    	console.log( "watchEffect配置的回调执行了")
    })

    例如还用上边的例子:

    import {reactive,watchEffect} from 'vue'
    export default {
      name: 'Demo',
      setup() {
        let person = reactive({
          name: "张三",
          age: 18,
          job:{
            j1:{
              salary:20
            }
          }
        })
        watchEffect(()=>{
          const x1 = person.name;
          console.log("watchEffect所指定的回调执行了"+x1);
        })
        return {
          person
        }
      }
    }
    </script>

    可以看到用到了哪个就监视哪个

    最后,我们使用 watch 和 watchEffect 实现姓名的例子

    <template>
      姓:<input v-model="person.firstName">
      名:<input  v-model="person.lastName">
      <span>全名:{{fullName}}</span>
      <span>全名:<input v-model="fullName"></span>
    </template>
    <script lang="ts">
    import {defineComponent, reactive, ref,watch,watchEffect} from 'vue';
    export default defineComponent({
      setup(){
        let person = reactive({
          firstName:"张",
          lastName:"三"
        });
    
        const fullName = ref('');
    
        watch(person,({firstName,lastName})=>{
          fullName.value = firstName+"-"+lastName
        },{immediate:true})
    
        //不用使用immediate,默认执行一次
        /*watchEffect(()=>{
          fullName.value = person.firstName+"-"+person.lastName
        })*/
    
        watchEffect(()=>{
          const name = fullName.value.split('-');
          person.firstName = name[0];
          person.lastName = name[1];
        })
        return{
          person,
          fullName
        }
      }
    });
    </script>
    <style>
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>

    在线客服
    服务热线

    服务热线

    4008888355

    微信咨询
    二维码
    返回顶部
    ×二维码

    截屏,微信识别二维码

    打开微信

    微信号已复制,请打开微信添加咨询详情!