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

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

在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

備註

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

 


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

-Advertisement-
Play Games
更多相關文章
  • 前言 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 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...