Vue【資料】計算屬性和偵聽器
筆記內容:學習編寫能夠讓模板產生響應式變化的資料。
目錄:
眾所周知,Vue是一個響應式的前端元件框架。響應式即是當業務邏輯中的資料發生改變的時候檢視中的內容也會跟著改變。
計算屬性和偵聽器
例子
假設班上有許一、許二、許三三位同學,在頁面中,名字名字前面是序號,名字後面是獲得小紅花的數字。
<template> <div class="hello"> <div v-for="(p, index) in classmates" :key="p.id"> {{ `${index}.${p.name}` }} : {{ p.count }}View Code<button @click="add(index)">+</button> <button @click="del(index)">-</button> </div> </div> </template> <script> export default { data(){ return{ classmates: [ {id: 1, name: "許一", count: 0}, {id:2, name: "許二", count: 0}, {id: 3, name: "許三", count: 0}, ] }; }, methods: { add(i){ this.classmates[i].count += 1; }, del(i){ this.classmates[i].count -= 1; } } } </script>
第13-21行:定義資料結構,通過函式 data 返回陣列 classmates。 第3-7行:通過 v-for 生成一個模板,classmates 是陣列,p 是當 前的值,index 是當前索引。設定“+”“-”按鈕,點選“+”按鈕呼叫 add 方法(第23-25行),add 的引數 index 是當前索引,對應數 組 classmate 中元素在陣列中的索引。點選“-”按鈕呼叫 del 方法(第26-28行)程式碼說明
下面實現:計算班級同學獲得的小紅花的總數 count, 在頁面上顯示出來。
有幾種實現方案。
方案 1 :通過計算屬性實現
<template> <div class="hello"> <div v-for="(p, index) in classmates" :key="p.id"> {{ `${index}.${p.name}` }} : {{ p.count }} <button @click="add(index)">+</button> <button @click="del(index)">-</button> </div> <div> count: {{count}} </div> </div> </template> <script> export default { data(){ return{ classmates: [ {id: 1, name: "許一", count: 0}, {id: 2, name: "許二", count: 0}, {id: 3, name: "許三", count: 0}, ] }; }, computed: { count(){ return this.classmates.reduce((p, c) => { p = p + c.count; return p; }, 0) } }, methods: { add(i){ this.classmates[i].count += 1; }, del(i){ this.classmates[i].count -= 1; } } } </script>View Code
第21-31行:
reduce() 方法接收一個函式作為累加器,陣列中的每個值(從左到右)開始縮減,最終計算為一個值。
p 是初始值,計算後的返回值
c 是當前元素
0 是傳遞給函式的初始值
可以參考:
https://www.runoob.com/jsref/jsref-reduce.html
相關筆記:
https://www.cnblogs.com/xiaoxuStudy/p/12604515.html#map
程式碼說明
頁面表現:
點選按鈕分別給許一、許二、許三新增小紅花,count 處輸出小紅花總數。
方案 2 :通過方法實現
<template> <div class="hello"> <div v-for="(p, index) in classmates" :key="p.id"> {{ `${index}.${p.name}` }} : {{ p.count }} <button @click="add(index)">+</button> <button @click="del(index)">-</button> </div> <div> count: {{count()}} </div> </div> </template> <script> export default { data(){ return{ classmates: [ {id: 1, name: "許一", count: 0}, {id: 2, name: "許二", count: 0}, {id: 3, name: "許三", count: 0}, ] }; }, methods: { count(){ return this.classmates.reduce((p, c) => { p = p + c.count; return p; }, 0) }, add(i){ this.classmates[i].count += 1; }, del(i){ this.classmates[i].count -= 1; } } } </script>View Code
頁面表現同上。
方案 1 跟方案 2 的區別
通過計算屬性實現比通過方法實現效能好。
通過計算屬性實現
計算屬性是基於其內部的響應式依賴進行快取的,只有相關響應式依賴發生改變時它們才會重新求值。
上面方案 1 例子中 computed 依賴的是 this.classmates,只有 this.classmates 發生改變的時候 count 函式才會進行一次計算,計算以後模板就會進行更新重新渲染。
通過方法實現
方法是無快取的,每當觸發重新渲染時,呼叫方法總會再次執行函式。
計算屬性是基於其內部的響應式依賴進行快取的
在實際的元件使用的過程中,如果希望在模板中去使用常量內容又不希望將常量內容放在 data 裡去做響應式依賴收集,可以利用 computed 的快取特性,將模板中使用的常量內容放到計算屬性中。
偵聽器就是一個 watch 函式,watch能夠偵聽資料例項上的變化。
用途:在資料變化後執行非同步操作或者開銷較大的操作
watch 函式跟 computed 函式都能偵聽資料上的變化,但是,computed 是依賴資料的變化然後進行計算的,如果這個計算比較消耗時間、消耗資料量比較大或者消耗記憶體是會阻塞渲染的,所以,在這種情況下就不建議放到 computed 裡去做。如果,在資料變化後需要執行非同步操作或者開銷比較大的操作,建議放到 watch 函式裡面去做。
例子
<template> <div> {{ count }} <button @click="count = count + 1">add</button> </div> </template> <script> const log = index => index; export default { data(){ return{ count: 0 }; }, watch: { count(){ log(this.count); } } } </script>View Code
頁面表現:
點選按鈕,按鈕前面的數字跟著變化,比如,點選 3 次按鈕之後,頁面表現: