前端學習-vue影片學習006-watch監視、watchEffect

ayubene發表於2024-03-05

尚矽谷影片連結

watch監視的5種情況

情況1 監視【ref】定義的【基本型別】資料

<template>
    <div class="person">
        <h1>情況1:監視【ref】定義的【基本型別】資料</h1>
        <h2>求和:{{ sum }}</h2>
        <button @click="changeSum">sum+1</button>
    </div>
</template>

<script lang="ts" setup name="Person">
    import {ref,watch} from 'vue'
    
    let sum = ref(0)
    function changeSum() {
        sum.value += 1
    }
    // 增加監視
    // watch(sum,(newVal,oldVal)=>{
    //     console.log('sum changed',newVal,oldVal);
    // })
    // 停止監視
    const stopWatch = watch(sum,(newVal,oldVal)=>{
        console.log('sum changed',newVal,oldVal);
        if(newVal >= 10) {
            stopWatch()
        }
        return 0
    })
</script>

<style scoped>
    .person {
        background-color: skyblue;
        box-shadow: 0 0 10px;
        border-radius: 10px;
        padding: 20px;
    }
    
    button {
        margin : 0 5px;
    }

    li {
        font-size : 20px;
    }
</style>

情況2:監視【ref】定義的【物件型別】資料

<template>
    <div class="person">
        <h1>情況2:監視【ref】定義的【物件型別】資料</h1>
        <h2>姓名:{{person.name}}</h2>
        <h2>年齡:{{person.age}}</h2>
        <button @click="changeName">changeName</button>
        <button @click="changeAge">changeAge</button>
        <button @click="changePerson">changePerson</button>
    </div>
</template>

<script lang="ts" setup name="Person">
    import {ref,watch} from 'vue'
    
    let person = ref({
        name:'zhangsan',
        age:20
    })
    function changeName(){
        person.value.name = 'lisi'
    }
    function changeAge(){
        person.value.age++
    }
    function changePerson(){
        person.value = {name:'lalala',age:30}
    }
    // 僅監視物件的地址值,當整個物件發生變化時,監視生效
    // watch(person,(newVal,oldVal)=>{
    //     console.log(newVal,oldVal);
    // })

    // 監視物件內部值的變化(開啟深度監視deep 問題:此時由於物件沒有變化,因此取到的新、舊值均為新值
    watch(person,(newVal,oldVal)=>{
        console.log(newVal,oldVal);
    },{deep:true})


</script>

<style scoped>
    .person {
        background-color: skyblue;
        box-shadow: 0 0 10px;
        border-radius: 10px;
        padding: 20px;
    }
    
    button {
        margin : 0 5px;
    }

    li {
        font-size : 20px;
    }
</style>

情況3:監視【reactive】定義的【物件型別】資料

  • 預設開啟深度監視,無法關閉
<template>
    <div class="person">
        <h1>情況3:監視【reactive】定義的【物件型別】資料</h1>
        <h2>姓名:{{person.name}}</h2>
        <h2>年齡:{{person.age}}</h2>
        <button @click="changeName">changeName</button>
        <button @click="changeAge">changeAge</button>
        <button @click="changePerson">changePerson</button>
    </div>
</template>

<script lang="ts" setup name="Person">
    import {reactive,watch} from 'vue'
    
    let person = reactive({
        name:'zhangsan',
        age:20
    })
    function changeName(){
        person.name = 'lisi'
    }
    function changeAge(){
        person.age++
    }
    function changePerson(){
        // person = {name:'lalala',age:30}
        // 僅修改物件內的值,物件地址不變
        Object.assign(person,{name:'lalala',age:30})
    }
    // 僅監視物件的地址值,當整個物件發生變化時,監視生效
    // watch(person,(newVal,oldVal)=>{
    //     console.log(newVal,oldVal);
    // })

    // 預設開啟深度監視
    watch(person,(newVal,oldVal)=>{
        console.log(newVal,oldVal)
    })

</script>

<style scoped>
    .person {
        background-color: skyblue;
        box-shadow: 0 0 10px;
        border-radius: 10px;
        padding: 20px;
    }
    
    button {
        margin : 0 5px;
    }

    li {
        font-size : 20px;
    }
</style>

情況4:監視【reactive/ref】定義的【物件型別】資料中的某個屬性

推薦使用:函式+深度

<template>
    <div class="person">
        <h1>情況4:監視【reactive/ref】定義的【物件型別】資料中的某個屬性</h1>
        <h2>姓名:{{person.name}}</h2>
        <h2>年齡:{{person.age}}</h2>
        <h2>車:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
        <button @click="changeName">changeName</button>
        <button @click="changeAge">changeAge</button>
        <button @click="changeC1">changeC1</button>
        <button @click="changeC2">changeC2</button>
        <button @click="changeCar">changeCar</button>
    </div>
</template>

<script lang="ts" setup name="Person">
    import {reactive,watch} from 'vue'
    
    let person = reactive({
        name:'zhangsan',
        age:20,
        car:{
            c1:'第一',
            c2:'第二'
        }
    })
    function changeName(){
        person.name += '!'
    }
    function changeAge(){
        person.age++
    }
    function changeC1(){
        person.car.c1 = '333'
    }
    function changeC2(){
        person.car.c2 = '444'
    }
    function changeCar(){
        person.car = {
            c1:'555',
            c2:'666'
        }
    }
    
    // 要監視的值不是物件,需要寫成函式
    watch(()=>person.name,(newVal,oldVal)=>{
        console.log('person.name changed',newVal,oldVal);
        
    })

    // 要監視是值仍然是物件,可以直接寫,但建議寫成函式
    // 直接寫時,如果改變整個物件,則無法監視到
    watch(person.car,(newVal,oldVal)=>{
        console.log('person.car changed',newVal,oldVal)
    },{deep:true})
    // 寫成函式+深度,可以監視到所有變化
    watch(()=>person.car,(newVal,oldVal)=>{
        console.log('person.car changed',newVal,oldVal)
    },{deep:true})

</script>

<style scoped>
    .person {
        background-color: skyblue;
        box-shadow: 0 0 10px;
        border-radius: 10px;
        padding: 20px;
    }
    
    button {
        margin : 0 5px;
    }

    li {
        font-size : 20px;
    }
</style>

情況5:監視上述的多個資料

使用陣列

watch([()=>person.car.c1,()=>person.name],(newVal,oldVal)=>{
    console.log('person.car changed',newVal,oldVal)
},{deep:true})

watchEffect

    // 使用watch,需要監視這兩個資料(如果有10個資料,要監視10個
    // watch([temp,height],()=>{
    //     if(temp.value > 50 || height.value > 70){
    //         console.log('hhhhhhhhhhhh')
    //     }
    // })

    // 使用watchEffect,自動監視所有變化的資料
    watchEffect(()=>{
        if(temp.value > 50 || height.value > 70){
            console.log('hhhhhhhhhhhh')
        }
    })

相關文章