1、數據持久化 (本地存儲)
1. 可以在數組的`增刪改`, 都要保存一下, 比較繁瑣
2. 監聽數組的變化, 數組一旦發生變化, 在監聽里面 保存一下(代碼寫一遍就可以了)
vue 提供了一個監聽器.
TodoMVC 數據持久化
需求 : 將todoMVC中的數據, 保存到
本地存儲中 (本地持久化)
-
何時存儲數據?
因為功能中的 CRUD 都會修改 list 數據,所以,只要 list 數據發生改變, 就要保存到本地存儲中;
方法一 : 在 CRUD 中 分別調用保存數據的方法,(不推薦 太繁瑣)
方法二 : 想辦法監聽 list 數據的改變,只要 list 數據變了, 就調用保存數據的方法
可以使用 vue 的 watch 監聽 list 的數據改變
-
存儲值
監聽數組和監聽對象一樣 需要深度監聽
保存值, 記得把對象轉化為字符串(存的快 省空間)
// 監聽
watch: {
// 監聽list
todoList: {
deep: true,
handler(newVal) {
// console.log('發生變化了', newVal)
// 保存起來
localStorage.setItem('todoList', JSON.stringify(newVal))
}
}
}
-
取值 , 在 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設置監聽函數。
