381 vue 之 監聽 watch:數據持久化,監聽基本數據類型,監聽對象,計算屬性和watch的區別


1、數據持久化 (本地存儲)

1. 可以在數組的`增刪改`, 都要保存一下, 比較繁瑣
2. 監聽數組的變化, 數組一旦發生變化, 在監聽里面 保存一下(代碼寫一遍就可以了)

vue 提供了一個監聽器.

TodoMVC 數據持久化

需求 : 將todoMVC中的數據, 保存到 本地存儲中 (本地持久化)

  1. 何時存儲數據?

    因為功能中的 CRUD 都會修改 list 數據,所以,只要 list 數據發生改變, 就要保存到本地存儲中;
    方法一 : 在 CRUD 中 分別調用保存數據的方法,(不推薦 太繁瑣)
    方法二 : 想辦法監聽 list 數據的改變,只要 list 數據變了, 就調用保存數據的方法

可以使用 vue 的 watch 監聽 list 的數據改變

  1. 存儲值

    監聽數組和監聽對象一樣 需要深度監聽
    保存值, 記得把對象轉化為字符串(存的快 省空間)

// 監聽
watch: {
    // 監聽list
    todoList: {
        deep: true,
        handler(newVal) {
            // console.log('發生變化了', newVal)
            // 保存起來
            localStorage.setItem('todoList', JSON.stringify(newVal))
        }
    }
}
  1. 取值 , 在 data 中可以初始值

    記得給一個默認值 空數組 []

const todoList =  JSON.parse(localStorage.getItem('todoList')) || [],

2、說明

Vue 中可以通過 watch 配置項, 來監聽 vue 實例中數據的變化


3、基本使用

watch: {
    // 監聽name屬性的數據變化
    // 作用 : 只要name的值發生變化,這個方法就會被調用
    // 第一個參數 : 新值
    // 第二個參數 : 舊值,之前的前
    name(newVal,oldVal){
        console.log('新 :',newVal);
        console.log('舊 :',oldVal);
    }
}

4、基本使用案例

需求 : 監聽用戶名文本框字符個數(3-6),並顯示格式驗證

<input type="text" v-model="name" />
<span v-show="isShow">用戶名的字符 在 6-12之間</span> if
(/^[0-9a-zA-Z]{3,6}$/.test(newVal)) { 驗證 }

5、監聽對象 (數組也屬於對象)

// data :
 data: {
   obj: {
   name: 'zs'
   }
},
// 組件
<input type="text" v-model="obj.name" />
// 監聽

6、開始監聽對象的屬性

// 從對象的角度來監聽的
因為對象和數組都是引用類型, 引用類型變量存的是地址, 地址沒有變, 所以不會觸發watch
obj: {
  // 深度監聽 屬性的變化
  deep: true,
    // 立即處理 進入頁面就觸發
    immediate: true,
      // 數據發生變化就會調用這個函數  
      handler(newVal) {
    console.log(newVal.name);
  }
},
// 從屬性的角度來監聽
'obj.name'(newVal) {
  console.log('監聽對象的屬性', newVal);
}

7、計算屬性和watch的區別

computed 和 watch的區別
computed :  計算屬性
    - 1.根據已知值 ,得到一個新值 
    - 2. 新值隨着已知值(相關的數據)變化而變化 
        (1)計算屬性 ==> (得到的是)新值
        (2)計算屬性(num)  ==> 是別人影響了我

watch : 監聽器
1. 監聽 ==> (監聽)已知值
2. 監聽數據 (num2) => 是我影響到了別人

8、命名規則 : 數字 字母 _ $

let xxx = 'sex'

let obj = {
  'mg-name': 'zs',
  age: 20,
  // sex : '男'
  [xxx] : '男'
}

05-監聽器的基本使用-我的.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        [v-cloak] {
            display: none;
        }
    </style>
</head>

<body>
    <div id="app">
        <h1>{{ num }}</h1>
        <button @click="fn">按鈕</button>
    </div>

    <script src="./vue.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                num: 100,
                msg: {}
            },
            methods: {
                fn() {
                    for (let i = 0; i < 5; i++) {
                        this.num++
                    }
                }
            },
            watch: {
                num(newVal, oldVal) {
                    console.log(`新值是:${newVal},舊值是:${oldVal}`); // 新值是:105,舊值是:100
                }
            }
        })
    </script>

</body>

</html>
<script>
</script>

06-監聽器監聽復雜類型.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>

<body>
    <div id="app">
        <input type="text" v-model="obj.name" />
    </div>
    <script src="./vue.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                obj: {
                    name: 'zs'
                }
            },
            // 監聽
            watch: {
                // 監聽 obj ,如果監聽成功 newVal 就是obj的最新值 newVal 也是對象
                // 因為obj是復雜類型 引用類型,直接這么寫,監聽的是對象的地址 【所以只有地址發送改變時,才會監聽到。】
                // obj(newVal) {
                //   console.log(newVal.name)
                // }

                // 方式1 : 監聽對象+ 深度監聽 【注意語法】
                obj: {
                    deep: true, // 深度監聽
                    immediate: true, // 立即監聽
                    // 處理
                    handler(newVal) {
                        console.log(newVal.name)
                    }
                },

                // 方式2: 簡單粗暴的直接監聽對象里的屬性(name)
                'obj.name' (newVal) {
                    console.log(newVal)
                }
            }
        })
    </script>
</body>

</html>

08-監聽器的小案例.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
  </head>
  <body>
    <!-- 
        需求 : 監聽文本框內容的字符串長度 (3-6) , 如果超過范圍,提示格式不正確
    -->
    <div id="app">
      <input type="text" v-model="msg" />
      <span v-show="isShow">格式不正確</span>
    </div>
    <script src="./vue.js"></script>
    <script>
      const vm = new Vue({
        el: '#app',
        data: {
          msg: '',
          isShow: false
        },
        watch: {
          msg(newVal) {
            if (newVal.length >= 3 && newVal.length <= 6) {
              console.log('格式正確')
              this.isShow = false
            } else {
              console.log('格式不正確')
              this.isShow = true
            }
          }
        }
      })
    </script>
  </body>
</html>

09-計算屬性和監聽器的區別.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>

<body>
    <!-- 
    計算屬性 computed       
    監聽器 watch

    計算屬性 : 
      - 根據已知值, 得到一個新值
      - 新值隨着`相關的數據`發生變化而變化
      - 是一個新值, 不是data里的值
      區別 :
        - 別人改變, 影響到了我
    
    監聽器
      - 監聽數據的變化  
      - 監聽的不是一個新值(可以是data里的值)
      
      區別 :
      - 我改變了, 去影響別人 【被監聽的數據改變了,會觸發一些操作。】 【當被監聽的數據改變了,就......】
   -->

    <div id="app"></div>
    <script src="./vue.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                num1: 100,
                num2: 200
            },
            computed: {
                totalNum() {
                    return this.num1 + 20
                }
            },
            watch: {
                num2(newVal) {
                    // console.log(newVal)
                    if (newVal <= 205) {
                        console.log('我想干第一件事')
                    } else {
                        console.log('我想干第二件事')
                    }
                }
            }
        })
    </script>
</body>

</html>

補充

偵聽屬性watch:

  • 不支持緩存,數據變,直接會觸發相應的操作;
  • watch支持異步
  • 監聽的函數接收兩個參數,第一個參數是最新的值;第二個參數是輸入之前的值
  • 當一個屬性發生變化時,需要執行對應的操作;一對多;
  • 監聽數據必須是data中聲明過或者父組件傳遞過來的props中的數據,當數據變化時,觸發其他操作,函數有兩個參數:

immediate:組件加載立即觸發回調函數執行

watch: {
  firstName: {
    handler(newName, oldName) {
      this.fullName = newName + ' ' + this.lastName;
    },
    // 代表在wacth里聲明了firstName這個方法之后立即執行handler方法
    immediate: true
  }
}

deep: deep的意思就是深入觀察,監聽器會一層層的往下遍歷,給對象的所有屬性都加上這個監聽器,但是這樣性能開銷就會非常大了,任何修改obj里面任何一個屬性都會觸發這個監聽器里的 handler。

watch: {
  obj: {
    handler(newName, oldName) {
      console.log('obj.a changed');
    },
    immediate: true,
    deep: true
  }
}

~

優化:我們可以使用字符串的形式監聽

watch: {
  'obj.a': {
    handler(newName, oldName) {
      console.log('obj.a changed');
    },
    immediate: true,
    // deep: true
  }
}

~

這樣Vue.js才會一層一層解析下去,直到遇到屬性a,然后才給a設置監聽函數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM