vue百宝箱3

47 阅读2分钟

watchEffect 使用的注意点

watchEffect(props.data, () => {if(!flag){ msg.value = 'xxx' }})

watchEffect(props.data, async() => {await fn(), msg.value = 'xxx'})

`对于有条件判断或者异步任务的情况下,msg 这个依赖在第一次执行的时候不会被收集到依赖,因为msg需要等到异步函数执行完才会被执行到,但是依赖手机是同步的,内部收集依赖并不会等到异步函数执行完毕- watchEffect 在第一次执行时,会立即开始执行回调函数

  • 当遇到 await fn() 时,函数会暂停执行
  • 此时 watchEffect 的依赖收集已经完成,但 msg.value 的赋值还没有执行
  • 所以 watchEffect 没有收集到 msg 的依赖`

vue3.5 新特性

watch 第二个参数 deep:2, once:true //表示只触发一次!!

这是vue3.5 新提出的一个优化方案,之前只要传递了{deep:true} ,开启对数据的深度监听,无论这个数据的层数是多深,都会持续的监听并且递归收集依赖,这对于性能的损耗是巨大的。 vue3.5 发布了 deep:2 可以传递一个数字,表示递归监听的深度,2 就表示只监听到2层,超过2后,数据的改变是不会触发视图的变化的,因为没有收集依赖。 if条件的好理解,就是第一次不满足条件,无法访问到msg这个依赖。 异步后面的msg,因为在依赖收集的过程中,vue底层不知道这个异步操作到何时结束,所以对于msg的访问会被


const data = ref([
{a:{b:{c:{d:1}}},e:2}
])

watch(data,(newval,oldval) =>{console.log(newVal)}, {deep:2})

onClick() {
    data[0].e = 3 // 会触发watch
    
    data[0].a.b.c.d ++ 
    //不会触发watch!!!
    
}

  1. props 可以有默认值

const {count = 0, msg="hello world"} = defineProps()

如果传递了props,那么就用传递的值, 否则就是用这里的默认值

watch(count,()=>{}) 这样是会直接报错的

正确的方式

watch(()=>count,() => {}), 必须传递一个函数才可以!!!

  1. useId() hook

import {useId} from 'vue'

const id = useId()

这个hook 保证每一个vue 实例里面的 id 都是不同的

但是多个vue实例在一个文件里面,不特殊处理就是一样的。

特殊处理:

给每个vue实例配置 prefix 前缀

image.png

3.useTemplateRef()


const button = ref()
// 之前的写法,button 必须要跟下面的一直

有了这个useTemplateRef

可以: const buttonRef = useTemplateRef<HTMLButtonElement>('button')
就可以把跟定义数据的ref 给区分开!!!


<el-button ref="button"></el-button>

  1. onWatcherCleanup()

import {onWatcherCleanup} from 'vue'

用于处理上一次watch监听的所有的副作用函数


const count = ref(0)

const onClick = () => {
 count.value++
}

watch(count,(newval)=>{
    const handler = () => {
     console.log('click', newval)
    }
    window.addEventListener('click',handler)
    // 不清楚上一次的副作用的话,后面每次点击都会触发两次的click事件
    
    onWatcherCleanup(()=> {
        removeEventListener('click', handler)
    })
}, {immediate:true})

第二种写法:

watch(count,(newval,oldVal, onCleanup)=>{
    const handler = () => {
     console.log('click', newval)
    }
    window.addEventListener('click',handler)
    // 不清楚上一次的副作用的话,后面每次点击都会触发两次的click事件
    
    onCleanup(()=> {
        removeEventListener('click', handler)
    })
}, {immediate:true})