文章目錄
- 計算屬性 computed
- computed 的使用方法
- computed 與 method 的區別
- 計算屬性完整寫法
- watch 偵聽器(監視器)
- 簡單寫法 → 簡單類型數據,直接監視
- 完整寫法 → 添加額外配置項
計算屬性 computed
computed 的使用方法
**概念:**基于現有的數據,計算出來的新屬性。 依賴的數據變化,自動重新計算。
語法:
-
① 聲明在 computed 配置項中,一個計算屬性對應一個函數
-
② 使用起來和普通屬性一樣使用 {{ 計算屬性名 }}
computed: {計算屬性名 () {基于現有數據,編寫求值邏輯return 結果}
},
計算屬性 → 可以將一段 求值的代碼 進行封裝
示例:
? 要求:
通過計算屬性來求得獲得的禮物的總數
代碼:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>table {border: 1px solid #000;text-align: center;width: 240px;}th,td {border: 1px solid #000;}h3 {position: relative;}</style>
</head><body><div id="app"><h3>小黑的禮物清單</h3><table><tr><th>名字</th><th>數量</th></tr><tr v-for="(item, index) in list" :key="item.id"><td>{{ item.name }}</td><td>{{ item.num }}個</td></tr></table><!-- 目標:統計求和,求得禮物總數 --><p>禮物總數:{{getSum}} 個</p></div><script src="./vue.js"></script><script>const app = new Vue({el: '#app',data: {// 現有的數據list: [{ id: 1, name: '籃球', num: 1 },{ id: 2, name: '玩具', num: 2 },{ id: 3, name: '鉛筆', num: 5 },]},computed: {getSum() {return this.list.reduce((sum, item) => {return sum + item.num}, 0)}}})</script>
</body></html>
computed 與 method 的區別
computed 計算屬性:
**作用:**封裝了一段對于數據的處理,求得一個結果。
語法:
-
① 寫在 computed 配置項中
-
② 作為屬性,直接使用 → this.計算屬性 {{ 計算屬性 }}
methods 方法:
**作用:**給實例提供一個方法,調用以處理業務邏輯。
語法:
-
① 寫在 methods 配置項中
-
② 作為方法,需要調用 → this.方法名( ) {{ 方法名() }} @事件名=“方法名”
二者的區別
緩存特性(提升性能):
-
計算屬性會對計算出來的結果緩存,再次使用直接讀取緩存,依賴項變化了,會自動重新計算 → 并再次緩存
-
而方法卻是每次獲取值的時候都會重新計算
示例:
使用 computed 方法
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>table {border: 1px solid #000;text-align: center;width: 300px;}th,td {border: 1px solid #000;}h3 {position: relative;}span {position: absolute;left: 145px;top: -4px;width: 16px;height: 16px;color: white;font-size: 12px;text-align: center;border-radius: 50%;background-color: #e63f32;}</style>
</head><body><div id="app"><h3>小黑的禮物清單🛒<span>?</span></h3><table><tr><th>名字</th><th>數量</th></tr><tr v-for="(item, index) in list" :key="item.id"><td>{{ item.name }}</td><td>{{ item.num }}個</td></tr></table><p>禮物總數:{{ totalCount }} 個</p><p>禮物總數:{{ totalCount }} 個</p><p>禮物總數:{{ totalCount }} 個</p></div><script src="./vue.js"></script><script>const app = new Vue({el: '#app',data: {// 現有的數據list: [{ id: 1, name: '籃球', num: 3 },{ id: 2, name: '玩具', num: 2 },{ id: 3, name: '鉛筆', num: 5 },]},methods: {f_totalCount() {let total = this.list.reduce((sum, item) => sum + item.num, 0)console.log('methods方式獲取值被觸發了1次');return total}},computed: {totalCount() {let total = this.list.reduce((sum, item) => sum + item.num, 0)console.log('computed方式獲取值被觸發了1次');return total}},})</script>
</body></html>
使用 methods 方法
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>table {border: 1px solid #000;text-align: center;width: 300px;}th,td {border: 1px solid #000;}h3 {position: relative;}span {position: absolute;left: 145px;top: -4px;width: 16px;height: 16px;color: white;font-size: 12px;text-align: center;border-radius: 50%;background-color: #e63f32;}</style>
</head><body><div id="app"><h3>小黑的禮物清單🛒<span>?</span></h3><table><tr><th>名字</th><th>數量</th></tr><tr v-for="(item, index) in list" :key="item.id"><td>{{ item.name }}</td><td>{{ item.num }}個</td></tr></table><p>禮物總數:{{ f_totalCount() }} 個</p><p>禮物總數:{{ f_totalCount() }} 個</p><p>禮物總數:{{ f_totalCount() }} 個</p></div><script src="./vue.js"></script><script>const app = new Vue({el: '#app',data: {// 現有的數據list: [{ id: 1, name: '籃球', num: 3 },{ id: 2, name: '玩具', num: 2 },{ id: 3, name: '鉛筆', num: 5 },]},methods: {f_totalCount() {let total = this.list.reduce((sum, item) => sum + item.num, 0)console.log('methods方式獲取值被觸發了1次');return total}},computed: {totalCount() {let total = this.list.reduce((sum, item) => sum + item.num, 0)console.log('computed方式獲取值被觸發了1次');return total}},})</script>
</body></html>
計算屬性完整寫法
計算屬性默認的簡寫,只能讀取訪問,不能 “修改”。
如果要 “修改” → 需要寫計算屬性的完整寫法。
如果修改 computed 的值而其沒有 set 函數的話就會報錯
例子:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app">姓:<input type="text" v-model="firstName"><br>名:<input type="text" v-model="lastName"><br><p>姓名:{{fullName}}</p><button @click="changeName">修改姓名</button></div><script src="./vue.js"></script><script>const app = new Vue({el: '#app',data: {firstName: '迪',lastName: '幻'},computed: {fullName: {get() {return this.firstName + this.lastName},set(value) {this.firstName = value.slice(0, 1)this.lastName = value.slice(1)}}},methods: {changeName() {this.fullName = '迪小幻'}}})</script>
</body></html>
**總結:**如果你的計算屬性不止想拿來進行讀取操作的話,那么加上一個set方法就可以實現數據的讀取與改寫
watch 偵聽器(監視器)
作用:監視數據變化,執行一些 業務邏輯 或 異步操作。
語法:
-
① 簡單寫法 → 簡單類型數據,直接監視
-
② 完整寫法 → 添加額外配置項
簡單寫法 → 簡單類型數據,直接監視
data: { words: '蘋果',obj: {words: '蘋果'}
},
watch: {
// 該方法會在數據變化時,觸發執行數據屬性名 (newValue, oldValue) {一些業務邏輯 或 異步操作。
},'對象.屬性名' (newValue, oldValue) {一些業務邏輯 或 異步操作。}
}
示例:
簡單數據類型:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>* {margin: 0;padding: 0;box-sizing: border-box;font-size: 18px;}#app {padding: 10px 20px;}.query {margin: 10px 0;}.box {display: flex;}textarea {width: 300px;height: 160px;font-size: 18px;border: 1px solid #dedede;outline: none;resize: none;padding: 10px;}textarea:hover {border: 1px solid #1589f5;}.transbox {width: 300px;height: 160px;background-color: #f0f0f0;padding: 10px;border: none;}.tip-box {width: 300px;height: 25px;line-height: 25px;display: flex;}.tip-box span {flex: 1;text-align: center;}.query span {font-size: 18px;}.input-wrap {position: relative;}.input-wrap span {position: absolute;right: 15px;bottom: 15px;font-size: 12px;}.input-wrap i {font-size: 20px;font-style: normal;}</style>
</head><body><div id="app"><!-- 條件選擇框 --><div class="query"><span>翻譯成的語言:</span><select><option value="italy">意大利</option><option value="english">英語</option><option value="german">德語</option></select></div><!-- 翻譯框 --><div class="box"><div class="input-wrap"><textarea v-model="words"></textarea><span><i>??</i>文檔翻譯</span></div><div class="output-wrap"><div class="transbox">mela</div></div></div></div><script src="./vue.js"></script><script src="./axios.js"></script><script>// 接口地址:https://applet-base-api-t.itheima.net/api/translate// 請求方式:get// 請求參數:// (1)words:需要被翻譯的文本(必傳)// (2)lang: 需要被翻譯成的語言(可選)默認值-意大利// -----------------------------------------------const app = new Vue({el: '#app',data: {words: '',// obj: {// words: ''// }},watch: {words(newVal, oldVal) {console.log('words 的值變化了', 'newVal:' + newVal, 'oldVal:' + oldVal);}}})</script>
</body></html>
復雜數據類型:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>* {margin: 0;padding: 0;box-sizing: border-box;font-size: 18px;}#app {padding: 10px 20px;}.query {margin: 10px 0;}.box {display: flex;}textarea {width: 300px;height: 160px;font-size: 18px;border: 1px solid #dedede;outline: none;resize: none;padding: 10px;}textarea:hover {border: 1px solid #1589f5;}.transbox {width: 300px;height: 160px;background-color: #f0f0f0;padding: 10px;border: none;}.tip-box {width: 300px;height: 25px;line-height: 25px;display: flex;}.tip-box span {flex: 1;text-align: center;}.query span {font-size: 18px;}.input-wrap {position: relative;}.input-wrap span {position: absolute;right: 15px;bottom: 15px;font-size: 12px;}.input-wrap i {font-size: 20px;font-style: normal;}</style>
</head><body><div id="app"><!-- 條件選擇框 --><div class="query"><span>翻譯成的語言:</span><select><option value="italy">意大利</option><option value="english">英語</option><option value="german">德語</option></select></div><!-- 翻譯框 --><div class="box"><div class="input-wrap"><textarea v-model="obj.words"></textarea><span><i>??</i>文檔翻譯</span></div><div class="output-wrap"><div class="transbox">mela</div></div></div></div><script src="./vue.js"></script><script src="./axios.js"></script><script>// 接口地址:https://applet-base-api-t.itheima.net/api/translate// 請求方式:get// 請求參數:// (1)words:需要被翻譯的文本(必傳)// (2)lang: 需要被翻譯成的語言(可選)默認值-意大利// -----------------------------------------------const app = new Vue({el: '#app',data: {words: '',obj: {words: ''}},watch: {words(newVal, oldVal) {console.log('words 的值變化了', 'newVal:' + newVal, 'oldVal:' + oldVal);},'obj.words'(newVal, oldVal) {console.log('obj.words 的值變化了', 'newVal:' + newVal, 'oldVal:' + oldVal);}}})</script>
</body></html>
完整寫法 → 添加額外配置項
試想一下會有這樣一個情景,如果我們重新選擇一門語言的話,那翻譯的內容也會發生相應的改變,因此,我們就不能僅僅只檢測文本框內容是否發生了改變,還應該檢測語言的選擇是否發生了變化,因此我們就需要偵聽器的完整寫法來實現這一功能
偵聽器完整寫法
data: {obj: {words: '蘋果',lang: 'italy'},},watch: {// watch 完整寫法數據屬性名: {deep: true, // 深度監視immediate: true, // 是否立刻執行一次handlerhandler(newValue) {console.log(newValue)}}}
-
deep: true 對復雜類型深度監視
-
immediate: true 初始化立刻執行一次handler方法
因此我們改良后可以得到以下的代碼
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>* {margin: 0;padding: 0;box-sizing: border-box;font-size: 18px;}#app {padding: 10px 20px;}.query {margin: 10px 0;}.box {display: flex;}textarea {width: 300px;height: 160px;font-size: 18px;border: 1px solid #dedede;outline: none;resize: none;padding: 10px;}textarea:hover {border: 1px solid #1589f5;}.transbox {width: 300px;height: 160px;background-color: #f0f0f0;padding: 10px;border: none;}.tip-box {width: 300px;height: 25px;line-height: 25px;display: flex;}.tip-box span {flex: 1;text-align: center;}.query span {font-size: 18px;}.input-wrap {position: relative;}.input-wrap span {position: absolute;right: 15px;bottom: 15px;font-size: 12px;}.input-wrap i {font-size: 20px;font-style: normal;}</style>
</head><body><div id="app"><!-- 條件選擇框 --><div class="query"><span>翻譯成的語言:</span><select v-model="obj.lang"><option value="italy">意大利</option><option value="english">英語</option><option value="german">德語</option></select></div><!-- 翻譯框 --><div class="box"><div class="input-wrap"><textarea v-model="obj.words"></textarea><span><i>??</i>文檔翻譯</span></div><div class="output-wrap"><div class="transbox">mela</div></div></div></div><script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script><script>// 接口地址:https://applet-base-api-t.itheima.net/api/translate// 請求方式:get// 請求參數:// (1)words:需要被翻譯的文本(必傳)// (2)lang: 需要被翻譯成的語言(可選)默認值-意大利// -----------------------------------------------const app = new Vue({el: '#app',data: {words: '',obj: {words: '迪幻',lang: 'italy'}},watch: {obj: {deep: true,immediate: true,handler(newVal, oldVal) {console.log('被修改了', 'newVal:' + newVal, 'oldVal:' + oldVal);}}}})</script>
</body></html>
cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js">
相關文章:
- 本專欄上一章:
Vue.js - Vue 的安裝 以及 常用的 Vue 指令 【0基礎向 Vue 基礎學習】