与选项式API this.$watch(以及相应的watch选项)完全等效

和watchEffect区别:
	(1)不会立即执行,当侦听的源变更时才会执行
	(2)可以监听多个数据源
	(3)更具体地说明什么状态应该触发侦听器重新运行
	(4)访问侦听状态变化前后的值
	
相同:
	watch和watchEffect在停止侦听,清除副作用(相应地onInvalidate会作为回调的第三个参数传入),副作用刷新时机和侦听器调试等方面行为一致.

使用
	import { watch } from 'vue'
	
	setup(){
		(1)监听单个ref
			方式一:
				通过函数返回值
				watch(()=>{
					return x.value	一般用于监听对象中的单个属性,因为watch第一个参数类型得是对象
				},(state,preState)=>{
					...
				})
				
			方式二:
				通过直接放置ref
				watch(x,(state,preState)=>{
					...
				})
				
		(1.1)监听reactive对象
			 (1)数组:
				const array = reactive([1, 2, 3, 4])
				watch(
				  () => [...array],
				  (numbers, prevNumbers) => {
				    console.log(numbers, prevNumbers)
				  }
				)
		     (2)对象
				const obj= reactive({...})
				
				watch(
				  obj,	默认监听对象内所有属性的变更
				  (state, prevState) => {
				    console.log('not deep', state.attributes.name, prevState.attributes.name)
				  }
				)

				watch(
				  () => obj, 只有当返回不同的对象时,才会触发监听
				  (state, prevState) => {
				    console.log('not deep', state.attributes.name, prevState.attributes.name)
				  }
				)
				
			 (3)不能直接监听对象的普通属性(如number、string等),需要一个getter函数
				const obj = reactive({ count: 0 })
				
				这不起作用,因为你是向 watch() 传入了一个 number
					watch(obj.count, (count) => {
					  console.log(`count is: ${count}`)
					})
				
				提供一个 getter 函数
					watch(
					  () => obj.count,
					  (count) => {
					    console.log(`count is: ${count}`)
					  }
					)

				
		(1.5)具有和vue2中的watch等效的配置
			watch(x,fn,{
				immediate:true,	第一次就会执行回调
				deep:true		深度监视
				...
			})
				
		(2)监听多个数据源	
			watch([x,x1,...],([x,x1],[prex,prex1])=>{
				...
			})
			vue3.2:
			watch([x,x1,...], (newValues, prevValues) => {
				newValues	包含更新后的值[x,x1,..]
				prevValues	包含更新前的值[x,x1,..]
			})	
			
		(3)清除副作用、监听侦听器、要同步或在组件更新之前配置
			watch(x,(state,preState,onInvalidate)=>{
					...
					onInvalidate(){
						执行时机:
							在副作用即将重新执行时
							如果在setup()或生命周期钩子函数中使用了watchEffect, 则在卸载组件时
					}
				}),{
					flush: 'sync',    'pre'组件更新前运行
					
					onTrigger(e) {
				        依赖项变更导致副作用被触发时
				        e.taget包含了值
				    },
				    onTrack(e){
				    	当一个 reactive对象属性或一个 ref 作为依赖被追踪时触发
				    	e.taget包含了值
				    }
				}
			}
		
		(4)手动停止侦听:
			const xx=watch(...)
   	  		xx.stop();

2、卸载watch时机
	异步回调创建一个侦听器,那么它不会绑定到当前组件上,必须手动停止它,以防内存泄漏,同步则不用
	
	需要手动卸载:
	setTimeout(() => {
	  watch...
	}, 100)

代码示例:

<template>
  <div>
      <img src="./logo.png">
    <h1>Hello Vue 3!</h1>
    {{name}}{{obj.sex}}
    <button @click="inc">Clicked {{ count }} times.</button>
  </div>

</template>

<script>
import { ref,reactive,computed,readonly,watchEffect,watch } from 'vue'

export default {
  setup() {
    let count = ref(0)
    let count2=ref(2);
    let name = ref('jeff')
    const obj=reactive({sex:'male'})
    const robj=readonly(obj); 
    let timer;

    let r=readonly('aa') //不具有只读的能力

    watch(()=>{
      return count.value
    },(count,prevcount,onInvalidate)=>{
      console.log(count);
      console.log(prevcount);
      onInvalidate(()=>{
        console.log('清除');
      })
      
    },{
      onTrigger(e) {
        console.log(e);
      }
    })
    // watch(count,(count,prevcount)=>{
    //   console.log(count);
    //   console.log(prevcount);
    // })

  //   watchEffect((onInvalidate)=>{
  //     console.log(count.value);
  //     onInvalidate(()=>{
  //       console.log('清除');
  //       clearInterval(timer);
  //     })

  //   },  {
  //   onTrigger(e) {
  //     console.log(e);
  //   },
  //   onTrack(e)
  //   {
  //     console.log('triger');
  //     console.log(e)
  //   }
  // })
    


    const inc = () => {

       count.value++;
      // timer=setInterval(()=>{
      //   count.value++;
      // },1000)

    }

    return {
      count,
      inc,
      name, //在setup返回对象中自动解套
      obj
    }
  }
}
</script>

<style scoped>
img {
  width: 200px;
}
h1 {
  font-family: Arial, Helvetica, sans-serif;
}
</style>

Logo

前往低代码交流专区

更多推荐