Detailed explanation of the usage of watch monitoring in vue2 and vue3 (all)

Keywords: Front-end Vue Vue.js

First write a vue page

<template>
	<h1>Listen for a property</h1>
	<p>Summation:{{ sum }}</p>
	<button @click="sum++">Point I add 1</button><br />

	<h2>Listen for multiple properties</h2>
  	<p>{{ tipsmessage }}</p>
  	<button @click="tipsmessage += 1">Point I splice 1</button><br />

	<h1>listening object </h1>
 	<p>full name:{{ obj.name }}</p>
  	<p>Age:{{ obj.age }}</p>
  	<button @click="obj.age++">Point me plus age</button><br />

	<h1>Listening for a property change of an object</h1>
  	<p>Salary:{{ obj.test.salary }}</p>
  	<p>Working years:{{ obj.test.year }}</p>
  	<button @click="obj.test.salary += 1000">Give me a raise</button>
  	<button @click="obj.test.year++">Click me to add working years</button>

</template>

watch usage in Vue2

<script>
	data () {
    	return {
      		sum: 12,
      		tipsmessage: 'hell0',
      		obj: {
        		name: 'Lao Wang next door',
        		age: '30',
       		test: {
          		salary: 3000,
          		year: 1
        	}
      	}
    }
  },
  // Method 1: monitor the change of an attribute value in data. If you want to monitor the change of multiple attribute values, you can continue to write in
  watch: {
    sum(newVal, oldVal){
    	console.log('New value:', newVal)
        console.log('Old value:', oldVal)
   	   },
    tipsmessage (newVal, oldVal) {
        console.log('New value:', newVal)
        console.log('Old value:', oldVal)
       }
   }

// Method 2: monitor the changes of obj objects in data
//     For monitoring the changes of the whole object, you need to add deep, otherwise you can't monitor it; You can't listen to the change of an attribute value under the object. You can't listen to the specific value change. The new value is the same as the old value
	watch: {
            obj: {
                handler(newVal, oldVal) {
                    console.log('New value:', newVal)
                    console.log('Old value:', oldVal)
                },
                deep: true
            }
        }
// If you want to listen for specific attribute changes, such as changes in name and age, before executing the handler function, there are two methods: you need to use the calculated attribute as the middle layer or wrap the attribute in quotation marks

// Method 3: monitor the change of a specific attribute under the obj object in data - the first method uses computed as the middle layer
		computed: {
            getValue() {
                return this.obj.age
            }
        },
        watch: {
            getValule(newVal, oldVal) {
                console.log('New value:', newVal)
                console.log('Old value:', oldVal)
            }
            // Another way of writing
            getValue: {
                handler(newVal, oldVal) {
                    console.log('New value:', newVal)
                    console.log('Old value
                    : ', oldVal) 
                }
            }
        }

// Method 4: listen for the change of a specific attribute under the obj object in data - the second method is to wrap it in quotation marks
		watch: {
            'obj.age'(newVal, oldVal) {
                console.log('New value:', newVal)
                console.log('Old value:', oldVal)
            }
            // There is another way to write
            'obj.age': {
                handler(newVal, oldVal) {
                    console.log('New value:', newVal)
                    console.log('Old value:', oldVal)
                }
            }
        }
// Method 5: listen to the test object in the obj object in data - there is no good way for the time being

// Method 6: listen to the specific attribute values in the test object in the obj object in data -- or two methods
// 		Method 1: use the calculated attribute as the middle layer	
		computed: {
            getValue() {
                return this.obj.test.year
            }
        }
        watch: {
            getValue(newValue, oldValue) {
                console.log('New value:', newVal)
                console.log('Old value:', oldVal)
            }
            
            // Another way of writing
            getValue: {
                handler (newVal, oldVal){
                    console.log('New value:', newVal)
                    console.log('Old value:', oldVal)
                }
            }
        }
        
        // 	Method 2: directly use watch to listen and enclose it in parentheses
        watch: {
            'obj.test.year'(newVal, oldVal) {
                console.log('New value:', newVal)
                console.log('Old value:', oldVal)
            }
            
            // Another way of writing
            'obj.test.year': {
                handler(newVal, oldVal) {
                    console.log('New value:', newVal)
                    console.log('Old value:', oldVal)
                }
            }
        }
</script>

Summary:
1. Listen to the field properties in data in vue2, and directly use watch: {field name (newvalue, oldvalue) {statement}} to listen to the changes of this field
2. For monitoring the changes of objects and their attributes in data:
       (1) Listen to the whole object: use the method of watch: {obj: {handler(newVal,oldVal) {statement}, deep: true}}. Note that this method can only listen to the changes of the whole object, not the specific changes of an attribute value under the object. That is, when an attribute value under the object changes, listening with this method will execute the handler function, but the new data value obtained is the same as the old value (both new values), and the change cannot be monitored
       (2) There are two methods for listening to an attribute under an object:
                   1. Use the calculated attribute as the middle layer, and use watch to listen
                   2. The specific attributes of the object can be directly enclosed in quotation marks, and then use watch
3. Listen to the objects in the objects in data and a property under the objects in the objects
       (1) At present, I don't have any good methods for the objects in the object - but it should be solved by using $set
       (2) There are also two methods for listening to a property under an object in an object
                   1. Use the calculated attribute as the middle layer, and then use watch to listen eg: calculated: {getvalue() {return this. Obj. Test. Year}} Watch: {getValue (newval, oldval) {statement}}
                   2. A specific attribute value of an object in the object is directly enclosed in quotation marks, and then use watch eg: watch: {obj.test.year '(newVal,oldVal) {statement}}

watch usage in Vue3

<script>
	setup() {
		let sum = ref(122)
        let tipsmessage = ref('hello')
        const obj = reactive({
            name: 'Lao Wang next door',
            age: '30',
            test: {
                salary: 3000,
                year: 1
            }
        })

// Method 1: listen to a single basic data type (ref)
        watch( sum, ( newVal, oldVal ) => {
            console.log(newVal, oldVal)
        })

// Method 2: listen to multiple basic data types (ref)
        watch( [ sum, tipsmessage ], ( newVal, oldVal ) => {
            // [122, 'hello1'] after listening, it is found that both the new value and the old value are arrays
            console.log( newVal, oldVal )
        })

// Method 3: listening object (reactive)
        /*
        	vue3 Current problems:
        		 1.reactive And ref responsive proxy cannot listen and get the old value of the object correctly
     			2.Forced to turn on deep listening, invalid to turn off (invalid deep configuration)
        */
        watch(obj, (newVal, oldVal) => {
            console.log('New value:', newVal)
            console.log('Old value:', oldVal)
        })
        // This method cannot monitor the change of a specific attribute value, but only the change of the overall obj. The deep configuration is invalid


// Method 4: listen for a certain attribute value under the object - this method can listen for the change of specific attribute value
        watch(()=>obj.age, ( newVal, oldVal) => {
            console.log('New value:', newVal)
            console.log('Old value:', oldVal)
        })

// Method 5: monitor the changes of multiple attribute values under the object
        watch([() => obj.name, () => obj.age], (newVal, oldVal) => {
            console.log('New value:', newVal)
            console.log('Old value:', oldVal)
            // This print out is also in the form of an array
        })
// Method 6: monitor the changes of the whole object under the object - add deep. This writing method can only monitor the changes of the whole object, and cannot obtain the changes of a specific attribute value under the object in the object, that is, the printed new value is the same as the old value

		watch(() => obj.test, (newVal, oldVal) => {
      		console.log('New value 2', newVal)
      		console.log('Old value', oldVal)
    		}, { deep: true })
		// Another way of writing
		watch(obj.test, (newVal, oldVal) => {
      		console.log('New value 1', newVal)
      		console.log('Old value', oldVal)
    		}, { deep: true })

// Method 7: monitor the changes of specific attribute values in the object under the object 
        watch(() => obj.test.year, (newVal, oldVal) => {
            console.log('New value:', newVal)
            console.log('Old value:', oldVal)
        })

// Method 8: monitor the changes of multiple attribute values under the object
        watch([()=>obj.test.year, ()=> obj.test.salary], (newVal, oldVal) => {
            console.log('New value:', newVal)
            console.log('Old value:', oldVal)
        })

        return {
        	sum,
        	tipsmessage,
        	obj
        }
	}
</script>

Summary:
1. For the data of ref type, the method of () = > field name cannot be used. Instead, the method of writing value directly is used for listening. See methods 1 and 2 for examples
2. For the data of reactive type, do not listen by directly writing the attribute name: Watch (attribute name, (newval, oldval) = > {}), because although this method can execute the function, it can not listen to the change of the specific attribute value, and the printed new value is the same as the old value. Use the method of watch(() = > attribute name, (newval, oldval) = > {}), so that the change of value can be obtained correctly

Posted by sneamia on Tue, 26 Oct 2021 00:54:17 -0700