一起學Vue之計算屬性和偵聽器

来源:https://www.cnblogs.com/hsiang/archive/2019/12/11/12020120.html

在Vue開發中,模板內的表達式非常便利,但是設計它們的初衷是用於簡單運算的。在模板中放入太多的邏輯會讓模板過重且難以維護。當你想要在模板中多次引用相同表達式時,就會更加難以處理。所以,對於任何複雜邏輯,你都應當使用計算屬性。本文主要講解Vue中的計算屬性和偵聽器,僅供學習分享使用,如有不足之前,還請... ...


概述

在Vue開發中,模板內的表達式非常便利,但是設計它們的初衷是用於簡單運算的。在模板中放入太多的邏輯會讓模板過重且難以維護。當你想要在模板中多次引用相同表達式時,就會更加難以處理。所以,對於任何複雜邏輯,你都應當使用計算屬性。本文主要講解Vue中的計算屬性和偵聽器,僅供學習分享使用,如有不足之前,還請指正。

計算屬性

計算屬性步驟:

1. 在computed屬性中增加reverseMsg方法,如下所示:

 1 <script type="text/javascript">
 2     var vm = new Vue({
 3         el: '#app',
 4         data: {
 5             msg: 'welcome to vue world!!!'
 6 
 7         },
 8         computed: {
 9             reverseMsg: function() {
10                 // `this` 指向 vm 實例
11                 return this.msg.split('').reverse().join('');
12             }
13         }
14                 
15     });
16 </script>

2. 在Html中進行引用,你可以像綁定普通屬性一樣在模板中綁定計算屬性。

Vue 知道 vm.reverseMsg 依賴於 vm.msg,因此當 vm.msg 發生改變時,所有依賴 vm.reverseMsg 的綁定也會更新。如下所示:

1 <p>原始信息: {{ msg }}</p>
2 <p>計算屬性反轉信息: {{ reverseMsg }}</p>

採用表達式的方式 ,則是如下所示:

1 <span>{{ msg.split('').reverse().join('') }}</span>

在這個地方,模板不再是簡單的聲明式邏輯。你必須看一段時間才能意識到,這裡是想要顯示變數 msg 的翻轉字元串。此處對比一下,採用計算屬性的方式,則更加簡潔明瞭。

計算屬性緩存 vs 方法

你可能已經註意到我們可以通過在表達式中調用方法來達到同樣的效果,我們可以將同一函數定義為一個方法而不是一個計算屬性。兩種方式的最終結果確實是完全相同的。

如下所示,聲明一個方法:

 1 <script type="text/javascript">
 2     var vm = new Vue({
 3         el: '#app',
 4         data: {
 5             msg: 'welcome to vue world!!!'
 6         },
 7         methods: {
 8             reversedMsg: function() {
 9                 return this.msg.split('').reverse().join('');
10             }
11         }
12 
13     });
14 </script>

在Html中進行引用,如下所示:

1 <p>Reversed message: "{{ reversedMsg() }}"</p>

差異:不同的是計算屬性是基於它們的響應式依賴進行緩存的。 只在相關響應式依賴發生改變時它們才會重新求值。 這就意味著只要 msg 還沒有發生改變,多次訪問 reversedMsg計算屬性會立即返回之前的計算結果,而不必再次執行函數。 即:計算屬性只有當依賴屬性發生改變時,才重新計算,而函數需要每次都重新計算。
也同樣意味著下麵的計算屬性將不再更新,因為 Date.now() 不是響應式依賴:  相比之下,每當觸發重新渲染時,調用方法將總會再次執行函數。 

 1 <script type="text/javascript">
 2     var vm = new Vue({
 3         el: '#app',
 4         data: {
 5             msg: 'welcome to vue world!!!'
 6 
 7         },
 8         computed: {
 9             now: function() {
10                 return Date.now().toString();
11             }
12 
13         });
14 </script>

如下所示,將不會隨著時間的改變而觸發。

1 <p>{{now}}</p>

如果你不希望有緩存,請用方法來替代。

計算屬性 vs 偵聽屬性

如下所示:有兩個data屬性,firstName和lastName,fullName依賴說前兩個變化而變化。如果需要採用偵聽屬性,需要對firstName和lastName進行偵聽。

 1 <script type="text/javascript">
 2     var vm = new Vue({
 3         el: '#app',
 4         data: {
 5             firstName: 'Foo',
 6             lastName: 'Bar',
 7             fullName: 'Foo Bar',
 8         },
10         computed: {
11             fullName2: function() {
12                 return this.firstName + ' ' + this.lastName;
13             }
15         },
16         watch: {
17             firstName: function(val) {
18                 this.fullName = val + ' ' + this.lastName;
19             },
20             lastName: function(val) {
21                 this.fullName = this.firstName + ' ' + val;
22             }
24         }
26     });
27 </script>

上面代碼是命令式且重覆的。將它與計算屬性的版本進行比較。

1 <div id="demo">{{ fullName }}</div>
2 <div id="demo">{{ fullName2 }}</div>

如上所示:fullName採用偵聽屬性,fullName2採用計算屬性,對比一下,好得多了,不是嗎?

計算屬性的 setter

計算屬性預設只有 getter ,不過在需要時你也可以提供一個 setter :如下所示:

 1 fullName3: {
 2     //getter
 3     get: function() {
 4         return this.firstName + ' ' + this.lastName;
 5     },
 6     //setter
 7     set: function(newValue) {
 8         console.log('newValue=' + newValue);
 9         var names = newValue.split(' ');
10         this.firstName = names[0];
11         this.lastName = names[names.length - 1];
12     }
13 }

在UI中引用的方式是一樣的。當fullName3的值發生改變時,將更新firstName和lastName。

1 <p>{{fullName3}}</p>

偵聽器

雖然計算屬性在大多數情況下更合適,但有時也需要一個自定義的偵聽器。這就是為什麼 Vue 通過 watch 選項提供了一個更通用的方法,來響應數據的變化。當需要在數據變化時執行非同步或開銷較大的操作時,這個方式是最有用的。如下所示:

 1 <script type="text/javascript">
 2     var vm = new Vue({
 3         el: '#app',
 4         data: {
 5             question: '',
 6             answer: 'I cannot give you an answer until you ask a question!'
 7 
 8         },
 9         watch: {
10             // 如果 `question` 發生改變,這個函數就會運行
11             question: function(newQuestion, oldQuestion) {
12                 if (newQuestion == '') {
13                     this.answer = 'Waiting for you to stop typing...';
14                 } else {
15                     this.answer = '請回答';
16                 }
17             }
18         }
19     });
20 </script>

在頁面中綁定屬性

1 <p>Ask a yes/no question:
2     <input v-model="question">
3 </p>
4 <p>{{ answer }}</p>

在這個示例中,使用 watch 選項允許我們執行非同步操作 (訪問一個 API),限制我們執行該操作的頻率,併在我們得到最終結果前,設置中間狀態。這些都是計算屬性無法做到的。

在本示例中用的全部代碼 ,如下所示:

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <meta charset="utf-8">
  5         <title>一起學Vue之計算屬性和偵聽器</title>
  6         <!-- 開發環境版本,包含了有幫助的命令行警告 -->
  7         <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  8     </head>
  9     <body>
 10         <div id="app">
 11             <span>{{msg}}</span>
 12             <h2>計算屬性</h2>
 13             <!-- 
 14              模板內的表達式非常便利,但是設計它們的初衷是用於簡單運算的。在模板中放入太多的邏輯會讓模板過重且難以維護。例如:
 15              -->
 16             <br />
 17             <span>
 18                 {{ msg.split('').reverse().join('') }}
 19             </span>
 20             <!-- 
 21             在這個地方,模板不再是簡單的聲明式邏輯。你必須看一段時間才能意識到,這裡是想要顯示變數 msg 的翻轉字元串。
 22             當你想要在模板中多次引用此處的翻轉字元串時,就會更加難以處理。
 23             所以,對於任何複雜邏輯,你都應當使用計算屬性
 24              -->
 25             <p>原始信息: {{ msg }}</p>
 26             <p>計算屬性反轉信息: {{ reverseMsg }}</p>
 27             <!-- 
 28             這裡我們聲明瞭一個計算屬性 reverseMsg。我們提供的函數將用作屬性 vm.reverseMsg 的 getter 函數: 
 29              -->
 30             <!-- 
 31              你可以像綁定普通屬性一樣在模板中綁定計算屬性。Vue 知道 vm.reverseMsg 依賴於 vm.msg,
 32              因此當 vm.msg 發生改變時,所有依賴 vm.reverseMsg 的綁定也會更新。
 33               -->
 34             <h2>計算屬性緩存 vs 方法</h2>
 35             <p>Reversed message: "{{ reversedMsg() }}"</p>
 36             <!-- 
 37             你可能已經註意到我們可以通過在表達式中調用方法來達到同樣的效果: 
 38             -->
 39             <!-- 
 40             我們可以將同一函數定義為一個方法而不是一個計算屬性。兩種方式的最終結果確實是完全相同的。
 41             然而,不同的是計算屬性是基於它們的響應式依賴進行緩存的。 
 42             只在相關響應式依賴發生改變時它們才會重新求值。
 43             這就意味著只要 msg 還沒有發生改變,多次訪問 reversedMsg 計算屬性會立即返回之前的計算結果,而不必再次執行函數。
 44             即:計算屬性只有當依賴屬性發生改變時,才重新計算,而函數需要每次都重新計算。
 45              -->
 46             <!-- 
 47             也同樣意味著下麵的計算屬性將不再更新,因為 Date.now() 不是響應式依賴: 
 48             相比之下,每當觸發重新渲染時,調用方法將總會再次執行函數。
 49             如果你不希望有緩存,請用方法來替代
 50              -->
 51             <p>{{now}}</p>
 52             <h2>計算屬性 vs 偵聽屬性</h2>
 53             <div id="demo">{{ fullName }}</div>
 54             <!-- 
 55              上面代碼是命令式且重覆的。將它與計算屬性的版本進行比較:
 56              -->
 57             <div id="demo">{{ fullName2 }}</div>
 58             <!-- 
 59              好得多了,不是嗎?
 60              -->
 61             <h2>計算屬性的 setter</h2>
 62             <!-- 
 63              計算屬性預設只有 getter ,不過在需要時你也可以提供一個 setter :
 64              -->
 65             <p>{{fullName3}}</p>
 66             <h2>偵聽器</h2>
 67             <!-- 
 68              雖然計算屬性在大多數情況下更合適,但有時也需要一個自定義的偵聽器。
 69              這就是為什麼 Vue 通過 watch 選項提供了一個更通用的方法,來響應數據的變化。
 70              當需要在數據變化時執行非同步或開銷較大的操作時,這個方式是最有用的。
 71              -->
 72             <p>Ask a yes/no question:
 73                 <input v-model="question">
 74             </p>
 75             <p>{{ answer }}</p>
 76             <!-- 
 77              在這個示例中,使用 watch 選項允許我們執行非同步操作 (訪問一個 API),
 78              限制我們執行該操作的頻率,併在我們得到最終結果前,設置中間狀態。
 79              這些都是計算屬性無法做到的。
 80              -->
 81         </div>
 82         <script type="text/javascript">
 83             var vm = new Vue({
 84                 el: '#app',
 85                 data: {
 86                     msg: 'welcome to vue world!!!',
 87                     firstName: 'Foo',
 88                     lastName: 'Bar',
 89                     fullName: 'Foo Bar',
 90                     question: '',
 91                     answer: 'I cannot give you an answer until you ask a question!'
 92 
 93 
 94                 },
 95                 methods: {
 96                     reversedMsg: function() {
 97                         return this.msg.split('').reverse().join('')
 98                     }
 99                 },
100                 computed: {
101                     reverseMsg: function() {
102                         // `this` 指向 vm 實例
103                         return this.msg.split('').reverse().join('');
104                     },
105                     now: function() {
106                         return Date.now().toString();
107                     },
108                     fullName2: function() {
109                         return this.firstName + ' ' + this.lastName;
110                     },
111                     fullName3: {
112                         //getter
113                         get: function() {
114                             return this.firstName + ' ' + this.lastName;
115                         },
116                         //setter
117                         set: function(newValue) {
118                             console.log('newValue=' + newValue);
119                             var names = newValue.split(' ');
120                             this.firstName = names[0];
121                             this.lastName = names[names.length - 1];
122                         }
123                     }
124                 },
125                 watch: {
126                     firstName: function(val) {
127                         this.fullName = val + ' ' + this.lastName;
128                     },
129                     lastName: function(val) {
130                         this.fullName = this.firstName + ' ' + val;
131                     },
132                     // 如果 `question` 發生改變,這個函數就會運行
133                     question: function(newQuestion, oldQuestion) {
134                         if (newQuestion == '') {
135                             this.answer = 'Waiting for you to stop typing...';
136                         } else {
137                             this.answer = '請回答';
138                         }
139                     }
140 
141                 }
142 
143             });
144         </script>
145     </body>
146 </html>
View Code

備註

暴虎馮河,死而無悔者,吾不與也;必也,臨事而懼,好謀而成者也。

 


您的分享是我們最大的動力!

更多相關文章
  • 前言 Hello我又來了,快年底了,作為一個有抱負的碼農,我想給自己攢一個年終總結。自上上篇寫了手動搭建Redis集群和MySQL主從同步(非Docker)和上篇寫了動手實現MySQL讀寫分離and故障轉移之後,索性這次把資料庫中最核心的也是最難搞懂的內容,也就是索引,分享給大家。 這篇博客我會談談 ...
  • ###第一周:R基礎 rm(list = ls()) #ctr+L###矩陣相乘,函數diag()a=matrix(1:12,nrow=3,ncol=4)b=matrix(1:12,nrow=4,ncol=3)a%*%ba=matrix(1:16,nrow=4,ncol=4)diag(a)#返回對角 ...
  • ORACLE資料庫中,我們會使用一些SQL語句找出存在隱式轉換的問題SQL,其中網上流傳的一個SQL語句如下,查詢V$SQL_PLAN的欄位FILTER_PREDICATES中是否存在INTERNAL_FUNCTION: SELECT SQL_ID, PLAN_HASH_VALUEFROM V$SQ... ...
  • 在安裝neo4j之前,需要安裝Java JRE,並配置Java開發環境,然後安裝neo4j服務。 一、CentOS下安裝 1.下載Neo4j 去官網下載最新的neo4j,選擇社區版。地址:https://neo4j.com/download/other-releases/#releases 將本地下 ...
  • Frida介面功能介紹 Frida是個so級別的hook框架,它可以幫助開發、安全人員對指定的進程的so模塊進行分析。它主要提供了功能簡單的Python介面和功能豐富的JS介面,使得hook函數和修改so可以編程化,介面中包含了主控端與目標進程的交互介面。 目標進程的交互介面分為: JS介面 功能包 ...
  • 13. 高效繪圖 高效繪圖 不必要的效率考慮往往是性能問題的萬惡之源。 ——William Allan Wulf 在第12章『速度的曲率』我們學習如何用Instruments來診斷Core Animation性能問題。在構建一個iOS app的時候會遇到很多潛在的性能陷阱,但是在本章我們將著眼於有關 ...
  • Frida是什麼 我覺得官網已經說得很清楚了。簡單的說就是一款動態代碼檢測工具,可用於各種主流操作系統,這裡主要討論的是動態檢測Android系統裡面代碼運行情況。 Android版的Frida環境的搭建主要分為兩個部分,一部分是運行在Android機器上的代理工具 ,另一部分是Windows系統用 ...
  • 本來之前覺得Android項目優化系列的文章基本整理完畢了,但是近期看了一下《阿裡Android開發手冊》有了很多收穫,想再整理一篇,下麵就開始吧。 先在這裡列一下之前整理的文章及鏈接: Android 項目優化(一):項目代碼規範優化 Android 項目優化(二):啟動頁面優化 Android ...
一周排行
  • 比如要拆分“呵呵呵90909086676喝喝999”,下麵當type=0返回的是中文字元串“呵呵呵,喝喝”,type=1返回的是數字字元串“90909086676,999”, private string GetStrings(string str,int type=0) { IList<strin ...
  • Swagger一個優秀的Api介面文檔生成工具。Swagger可以可以動態生成Api介面文檔,有效的降低前後端人員關於Api介面的溝通成本,促進項目高效開發。 1、使用NuGet安裝最新的包:Swashbuckle.AspNetCore。 2、編輯項目文件(NetCoreTemplate.Web.c ...
  • 2020 年 7 月 30 日, 由.NET基金會和微軟 將舉辦一個線上和為期一天的活動,包括 微軟 .NET 團隊的演講者以及社區的演講者。本次線上大會 專註.NET框架構建微服務,演講者分享構建和部署雲原生應用程式的最佳實踐、模式、提示和技巧。有關更多信息和隨時瞭解情況:https://focu... ...
  • #abp框架Excel導出——基於vue #1.技術棧 ##1.1 前端採用vue,官方提供 UI套件用的是iview ##1.2 後臺是abp——aspnetboilerplate 即abp v1,https://github.com/aspnetboilerplate/aspnetboilerp ...
  • 前言 本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。 作者:碧茂大數據 PS:如有需要Python學習資料的小伙伴可以加下方的群去找免費管理員領取 input()輸入 Python提供了 input() 內置函數從標準輸入讀入一 ...
  • 從12年到20年,python以肉眼可見的趨勢超過了java,成為了當今It界人人皆知的編程語言。 python為什麼這麼火? 網路編程語言搜索指數 適合初學者 Python具有語法簡單、語句清晰的特點,這就讓初學者在學習階段可以把精力集中在編程對象和思維方法上。 大佬都在用 Google,YouT ...
  • 在社會上存在一種普遍的對培訓機構的學生一種歧視的現象,具體表現在,比如:當你去公司面試的時候,一旦你說了你是培訓機構出來的,那麼基本上你就涼了,那麼你瞞著不說,然後又通過了面試成功入職,但是以後一旦在公司被髮現有培訓經歷,可能會面臨被降薪,甚至被辭退,培訓機構出來的學生,在用人單位眼裡就是能力低下的 ...
  • from typing import List# 這道題看了大佬寫的代碼,經過自己的理解寫出來了。# 從最外圍的四周找有沒有為O的,如果有的話就進入深搜函數,然後深搜遍歷# 判斷上下左右的位置是否為Oclass Solution: def solve(self, board: List[List[s ...
  • import requests; import re; import os; # 1.請求網頁 header = { "user-agent":'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, li ...
  • import requests; import re; import os; import parsel; 1.請求網頁 header = { "user-agent":'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537. ...