[Transfer] The difference between watch and watchEffect (vue3)

The watch function and the watchEffect function are both listeners. There are certain differences in writing and usage. They are two different forms of the same function, but the bottom layer is the same.

Comparison between watch and watchEffect

watch
Watch explicitly specifies dependent data, and executes a callback function when the dependent data is updated.
It has a certain degree of laziness. It will not be executed when the page is displayed for the first time. It will only be executed when the data changes (it can become non-lazy when setting immediate: true, and it will be executed when the page is loaded for the first time).
The original value can be obtained when monitoring the responsive data defined by ref
It is necessary to specify both the monitored properties and the monitored callbacks

watchEffect
watchEffect automatically collects dependency data and re-executes itself when dependency data is updated.

Execute immediately, no laziness, it will be executed when the page is first loaded

The original value cannot be obtained, only the changed value can be obtained

There is no need to specify which attribute to monitor, whichever attribute is used in the monitoring callback will be monitored

In-depth analysis of watch function

The watch function has two pitfalls:

  • When monitoring the responsive data defined by reactive (the data is an object, because reactive can only define responses of array or object types): oldValue cannot be obtained correctly, and deep monitoring will be forced to be turned on, and the deep configuration will not take effect.
  • When monitoring an attribute in the responsive data defined by reactive, and the attribute is an object, then the deep configuration takes effect.

The specific usage of the watch function is reflected in the code below, with detailed comments.

<template>
    <div>
        <h2>The current sum is: {<!-- -->{sum}}</h2>
        <button @click="sum + + ">Click me + 1</button>
        
        <h2>The current information is: {<!-- -->{msg}} </h2>
        <!-- Click the button to splice! -->
        <button @click="msg + ='!'">Modify data</button>
        
        <h2>Name: {<!-- -->{person.name}}</h2>
        <h2>Age:{<!-- -->{person.age}}</h2>
        <h2>Salary: {<!-- -->{person.job.j1.salary}}</h2>
        <button @click="person.name + ='~'"> Modify name</button>
        <button @click="person.age + + "> Increase age</button>
        <button @click="person.job.j1.salary + + "> Increase salary</button>
    </div>
</template>

<script>
import {ref,reactive,watch,watchEffect} from 'vue'
export default {
   name:'demo',
   setup(){
       //data
       let sum = ref(0)
       let msg = ref('hello')
       let person = reactive({
           name:'zhangsan',
           age:'18',
           job:{
               j1:{
                   salary:20
               }
           }
       })
       //Monitoring (three parameters, the first is the monitored object, the second is the monitoring callback function, and the third is the monitoring configuration)

       //Scenario 1: Monitor a responsive data defined by ref
       watch(sum,(newValue,oldValue)=>{
           console.log('The value of sum has changed', newValue, oldValue)
       },{immediate:true,deep:true})
       //When the value of immediate is true, it means non-lazy immediate execution (false by default)
       //deep deep level trigger (setting deep here is meaningless)

       //Case 2: Monitor multiple responsive data defined by ref and write it in the form of an array

       watch([sum,msg],(newValue,oldValue)=>{
           console.log('sum or msg has changed', newValue, oldValue)
       })

       //Case 3: Monitor the responsive data defined by reactive
                //If the responsive data defined by reactive is monitored, oldValue cannot be obtained correctly.
                //If what is monitored is the responsive data defined by reactive, watch will force the in-depth monitoring to be turned on.

        //We found that changing any attribute of person will be monitored
        watch(person,(newValue,oldValue)=>{
            console.log('person changed',newValue,oldValue)
        })
        
        //We try to set deep:false to turn off deep monitoring (purpose: changing the value of the job will not be monitored by the watch)
        //But we found that deep:false did not take effect. The reason is that the watch monitors the responsive object defined by reactive. Deep monitoring is forced to be turned on by default.
        watch(person,(newValue,oldValue)=>{
            console.log('person changed',newValue,oldValue)
        },{deep:false})
        


      //Case 4: Monitor an attribute in the responsive data defined by reactive
       watch(()=>person.name,(newValue,oldValue)=>{
            console.log('person's job has changed', newValue, oldValue)
        })
         watch(()=>person.age,(newValue,oldValue)=>{
            console.log('person's job has changed', newValue, oldValue)
        })
        watch(()=>person.job,(newValue,oldValue)=>{
            console.log('person's job has changed', newValue, oldValue)
        })
        //From the above we found that changing name and age will trigger monitoring, but changing job will not
        //This is because the value of the name and age attributes is just a simple basic type data,
        //The value of the job attribute is an object, which is relatively deep. If you want to monitor it, you need to enable deep monitoring. The procedure is as follows:
        watch(()=>person.job,(newValue,oldValue)=>{
            console.log('person's job has changed', newValue, oldValue)
        },{deep:true})//If the job changes at this time, it will be monitored, and the deep configuration here will take effect.
        //It needs to be distinguished from case three. Here watch monitors a certain attribute in the object defined by reactive, while in case three watch monitors the object defined by reactive.

      //Scenario 5: Monitor certain attributes in the responsive data defined by reactive and write it in the form of an array
        watch([()=>person.name,()=>person.age],(newValue,oldValue)=>{
            console.log('person's name or age has changed', newValue, oldValue)
        })

       //Return an object (commonly used)
       return{
           sum,
           msg,
           person
       }
   }
}
</script>

watchcancel monitoring

const stop1 = watch(
  [() => nameObj.name, () => nameObj.name],
  ([curName, curEng], [prevName, curEng]) => {
    console.log(curName, curEng, "----", prevName, curEng);
    setTimeout(() => {
      stop();
    }, 5000);
  }
);

In-depth analysis of watchEffect function

The function usage is shown in the following code, with detailed comments:

<template>
    <div>
        <h2>The current sum is: {<!-- -->{sum}}</h2>
        <button @click="sum + + ">Click me + 1</button>
        
        <h2>The current information is: {<!-- -->{msg}} </h2>
        <!-- Click the button to splice! -->
        <button @click="msg + ='!'">Modify data</button>
        
        <h2>Name: {<!-- -->{person.name}}</h2>
        <h2>Age:{<!-- -->{person.age}}</h2>
        <h2>Salary: {<!-- -->{person.job.j1.salary}}</h2>
        <button @click="person.name + ='~'"> Modify name</button>
        <button @click="person.age + + "> Increase age</button>
        <button @click="person.job.j1.salary + + "> Increase salary</button>
    </div>
</template>

<script>
import {ref,reactive,watch,watchEffect} from 'vue'
export default {
   name:'demo',
   setup(){
       //data
       let sum = ref(0)
       let msg = ref('hello')
       let person = reactive({
           name:'zhangsan',
           age:'18',
           job:{
               j1:{
                   salary:20
               }
           }
       })
//As long as the data used in the callback specified inside the watchEffect function changes, the callback will be re-executed.
//There is only one parameter, which is the callback
    watchEffect(()=>{
        const x1 = sum.value//Because sum is responsive data defined by ref, it needs to be called using .value
        const x2 = person.age
        console.log('The callback configured by watchEffect was executed')
    })
           return{
           sum,
           msg,
           person
       }
   }
}
</script>

watchEffect cancel monitoring

const stop = watchEffect(() => {
  console.log(nameObj.name);
  setTimeout(() => {
    stop();
  }, 5000);
});

watchEffect and computed
watchEffect is a bit like computed:

  • But computed focuses on the calculated value (the return value of the callback function), so the return value must be written.
  • WatchEffect pays more attention to the process (the function body of the callback function), so there is no need to write a return value.
  • computed will not be called if the value is not used, but watchEffect will always be called once
<template>
    <div>
        <h2>The current sum is: {<!-- -->{sum}}</h2>
        <button @click="sum + + ">Click me + 1</button>
        
        <h2>The current information is: {<!-- -->{msg}} </h2>
        <!-- Click the button to splice! -->
        <button @click="msg + ='!'">Modify data</button>
        
        <h2>Name: {<!-- -->{person.name}}</h2>
        <h2>Age:{<!-- -->{person.age}}</h2>
        <h2>Salary: {<!-- -->{person.job.j1.salary}}</h2>
        <button @click="person.name + ='~'"> Modify name</button>
        <button @click="person.age + + "> Increase age</button>
        <button @click="person.job.j1.salary + + "> Increase salary</button>
    </div>
</template>

<script>
import {ref,reactive,watch,watchEffect, computed} from 'vue'
export default {
   name:'demo',
   setup(){
       //data
       let sum = ref(0)
       let msg = ref('hello')
       let person = reactive({
           name:'zhangsan',
           age:'18',
           job:{
               j1:{
                   salary:20
               }
           }
       })
       let person1 = reactive({
           firstName:'Zhang',
           lastName:'三'
       })
       //computed
       //Computed property - abbreviation (does not consider the case where the calculated property is modified)
       person1.fullName = computed(()=>{
           //Must contain return value
           return person1.firstName + '-' + person1.lastName
       })

       //Computed attributes - complete writing method (consider reading and writing)
       person1.fullName = computed({
           //Must contain return value
           get(){
               return person1.firstName + '-' + person1.lastName
           },
           set(value){
               const nameArr = value.split('-')
               person1.firstName = nameArr[0]
               person1.lastName = nameArr[1]
           }
       })
       //watchEffect
        //You don’t need to write to the return value
        watchEffect(()=>{
            const x1 = sum.value//Because sum is responsive data defined by ref, it needs to be called using .value
            const x2 = person.age
            console.log('The callback configured by watchEffect was executed')
        })
         return{
           sum,
           msg,
           person,
           person1
       }
   }
}
</script>

————————–
Author: ZXH0122
Source: CSDN
Original text: https://blog.csdn.net/ZXH0122/article/details/129794342
Copyright statement: This article is an original article by the author. Please attach a link to the blog post for reprinting!
Content analysis By: CSDN, CNBLOG blog article one-click reprint plug-in

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Java Skill TreeHomepageOverview 139018 people are learning the system