The use of vue3 in watch and watchEffect

Vue3's watch is a function that can receive three parameters. The first parameter is the monitored attribute, the second parameter is the callback function that receives the new value and the old value, and the third parameter is the configuration item.

<script setup>
import {
    
     watch, ref, reactive } from 'vue'
  props: ['info'],
const data = reactive({
    
    
	name:'Watch',
    age: 18,
    height: 180,
    children: [],
    money:10
})

// 监听 props属性
 watch(
        ()=>props,
        (val) => {
    
    
          if (!val) {
    
    
            return
          }
			data.money=props.info.money
			data.height=props.info.money
        }
      )

// 监听其他属性、路由或者状态管理的都这样
watch(
    () => data.age, 
    (newAge, oldAge) => {
    
     ... }
)

// 监听多个属性,数组放多个值,返回的新值和老值也是数组形式
watch([data.age, data.money], ([newAge, newMoney], [oldAge, oldMoney]) => {
    
     ... })

// 第三个参数是一个对象,为可配置项,有5个可配置属性
watch(data.children, (newList, oldList) => {
    
     ... }, {
    
    
    // 这两个和 Vue2 一样,没啥说的
    immediate: true,
    deep: true,
    // 回调函数的执行时机,默认在组件更新之前调用。更新后调用改成post
    flush: 'pre', // 默认值是 pre,可改成 post 或 sync
    // 下面两个是调试用的
    onTrack (e) {
    
     debugger }
    onTrigger (e) {
    
     debugger }
})
</script>

Regarding side effects
, the watch callback function can receive the third parameter onInvalidate. It is a function to clear side effects. The callback function (handler) that triggers the listener for the first time will not execute onInvalidate. After that, onInvalidate will be executed by default every time it is triggered, which means that it will be executed by default
. The mechanism is called before the update. For example, in the following code, when the key triggers the update, 222 will be printed first and then the watch will be printed. If it needs to be called after the update, you can add flush: post in the third configuration item of watch.

// 回调函数接收一个参数,为清除副作用的函数
watch(key, (newKey, oldKey, onInvalidate) => {
    
    
    console.log('Watch')
    // 获取DOM默认获取到的是更新前的dom,如果是flush: post,可以获取到更新后的dom
    console.log('DOM节点:', dom.innterHTML)
    onInvalidate(() => {
    
    
        console.log(2222)
    })
})

The usage scenario of onInvalidate is: for example, there are some asynchronous operations in the listening callback function (handler). When the watch is triggered again, you can use it to cancel/ignore/reset/initialize certain operations on the previously unfinished asynchronous tasks. For example, cancel the unfinished request when the watch was last triggered.

Note :

// 配置immediate参数,立即执行,以及深层次监听
 watch(data , (newValue, oldValue) => {
    
    
      // 回调函数
      console.log('触发监控更新了new',  newValue);
      console.log('触发监控更新了old',  oldValue);
    }, {
    
    
      immediate: true,
      deep: true
    })

If reactive data is defined and you want to use watch to monitor data changes, the old value cannot be obtained correctly, and the deep attribute configuration is invalid, and deep monitoring is automatically forced to be turned on.
If you use ref to initialize an object or array type data, it will be automatically converted to a reactive implementation and a proxy object will be generated. It will also become impossible to get the old value correctly.
If the data generated in any way is a proxy object, the old value cannot be correctly obtained in the watch callback when watching this object.
So when you use watch to monitor an object, if you don’t need to use the old value, you can monitor the object normally. But if you need to use the old value in the monitoring change function, you can only monitor the object.xxx attribute. .

watchEffect
The watchEffect function in Vue 3 is a responsive side effect function. Its principle can be divided into two stages.

Initialization phase : In the initialization phase, Vue 3 will convert the responsive data passed into watchEffect into a Pro object through the reactive function. The Pro object can intercept access and modification operations to responsive data and notify relevant side-effect codes when the data changes. After the initialization phase, the side effect code will be executed immediately, which ensures that the value of the responsive data before the first call of watchEffect is tracked.

Run phase : In the run phase, Vue 3 will wrap the side-effect code into a function and manage this function as a side-effect function of the current component. This side effect function will be executed when the component is rendered. During execution, the Pro object collects access to reactive data, thereby establishing dependencies between data and side effects. When the responsive data changes, the Pro object will trigger a dependency update, thereby notifying the relevant side effect code to be re-executed.

In addition to watch, Vue3 also adds a watchEffect. The difference is:

watch is to monitor one or more values ​​passed in, and will not be executed for the first time by default. It will only be executed when the monitored value changes. When triggered, the new value and the old value will be returned. watchEffect is used every time the code is loaded
. watchEffect will be executed, and there is no need to pass in the monitoring content. It will automatically collect the data sources within the function as dependencies. When the dependencies change, the function will be re-executed (a bit like computed), and new and old values ​​will not be returned.

Under normal circumstances, both will automatically stop monitoring after the component is destroyed/uninstalled, but there are exceptions. For example, in the asynchronous method, the monitoring created in setTimeout needs to be stopped manually. The stopping method is as follows

// 监听方法赋值
const unwatch = watch('key', callback)
const unwatchEffect = watchEffect(() => {
    
    })
// 需要停止监听的时候,手动调用停止监听
unwatch()
unwatchEffect()

How to use watchEffect

<script setup>
import {
    
     watchEffect } from 'vue'

// 正常使用
watchEffect(() => {
    
    
    // 会自动收集这个函数使用到的属性作为依赖,进行监听
    // 监听的是 userInfo.name 属性,不会监听 userInfo
    console.log(userInfo.name)
    
    // 如果是console.log(userInfo),就只会首次加载触发,
    //因为监控了整个对象,对象里面的值变化不会触发
})

// 有两个参数,参数一是触发监听回调函数,参数二是可选配置项
watchEffect(() => {
    
    ...}, {
    
    
    // 这里是可配置项,意思和 watch 是一样的,不过这只有3个可配置的
    flush: 'pre',
    //onTrack 将在响应式 property 或 ref 作为依赖项被追踪时被调用。
	//onTrigger 将在依赖项变更导致副作用被触发时被调用。
    onTrack (e) {
    
     debugger }
    onTrigger (e) {
    
     debugger }
})

// 回调函数接收一个参数,为清除副作用的函数,和 watch 的同理
watchEffect(onInvalidate => {
    
    
    console.log('watchEffect')
    onInvalidate(() => {
    
    
        console.log(2222)
    })
})
//比如:
watchEffect(onInvalidate => {
    
    
  const token = getUserInfo(id) // 获取用户信息
  onInvalidate(() => {
    
    
  //id已更改或观察程序已停止。使以前挂起的异步操作无效
    token.cancel()
  })
})

watchEffect If you need to modify the configuration item flush to post or sync, you can use the alias directly, as follows

watchEffect(() => {
    
    ...}, {
    
    
    flush: 'post',
})
// 和下面这个是一样的
watchPostEffect(() => {
    
    })
-----------------------------
watchEffect(() => {
    
    ...}, {
    
    
    flush: 'sync',
})
// 和下面这个是一样的
watchSyncEffect(() => {
    
    })

This is written at the end. Welcome everyone to leave comments and corrections~

Guess you like

Origin blog.csdn.net/m0_49016709/article/details/133027831