VueJS2: Computed Properties
Computed Properties dịch sang tiếng Việt rất khó hiểu nên mình sẽ dùng từ này như là một thuật ngữ trong VueJS luôn nhé. Tuy nhiên bạn có thể hiểu nôm na rằng Computed Properties là những hàm (methods) sử dụng để xử lý dữ liệu hiển thị lên template, kết quả của nó sẽ được lưu trữ (Cache) và chỉ cập nhật khi cần thiết. Ngoài ra ta cũng có thể xem computed là những phương thức setter và getter dùng để thiết lập dữ liệu và lấy dữ liệu đưa ra template.
1. Computed Properties
Chúng ta có rất nhiều cách để hiển thị dữ liệu ra View như: Sử dụng expression, sử dụng filters, sử dụng các directly binding (xem bài template syntax). Ngoài các cách đó ra thì chúng ta cũng có thể sử dụng computed properties để xử lý hiển thị dữ liệu hoặc thiết lập giá trị dữ liệu trong model.
Các expression
ở trong template rất là tiện lợi, tuy nhiên nó chỉ tiện cho các phép toán đơn giản, nếu bạn gặp phải những phép toán phức tạp thì nhìn vào template của bạn sẽ cồng kềnh và khó hiểu.
Ví dụ: Hiển thị đảo ngược giá trị của message, đây là ví dụ khá hay từ trang chủ của VueJS thể hiện sự rườm rà khi sử dụng expression quá phức tạp trong template.
Bài viết này được đăng tại [free tuts .net]
<div id="example"> <p>Giá trị ban đầu: "{{ message }}"</p> <p>Giá trị sau khi chuyển đổi: "{{ message.split('').reverse().join('') }}"</p> </div> <script language="javascript"> var vm = new Vue({ el: '#example', data: { message: 'Chào mừng đến với freetuts.net' } }); </script>
Nhưng nếu chúng ta sử dụng Computed thì nhìn sẽ dễ dàng hơn.
<div id="example"> <p>Giá trị ban đầu: "{{ message }}"</p> <p>Giá trị sau khi chuyển đổi: "{{ reverseMessage }}"</p> </div> <script language="javascript"> var vm = new Vue({ el: '#example', data: { message: 'Chào mừng đến với freetuts.net' }, computed : { reverseMessage : function(){ return this.message.split('').reverse().join(''); } } }); </script>
Như vậy tất cả các computed sẽ được đặt trong key computed nhé các bạn, giống như mọi data ta đều đặt trong key data.
2. Computed và Methods
Như ở ví dụ trên ta hoàn toàn có thể thay thế computed bằng methods như sau:
<div id="example"> <p>Giá trị ban đầu: "{{ message }}"</p> <p>Giá trị sau khi chuyển đổi: "{{ reverseMessage() }}"</p> </div> <script language="javascript"> var vm = new Vue({ el: '#example', data: { message: 'Chào mừng đến với freetuts.net' }, methods : { reverseMessage : function(){ return this.message.split('').reverse().join(''); } } }); </script>
Kết quả cũng không có gì khác nhau, vậy tại sao chúng ta lại dùng computed
thay vì dùng methods
? Câu trả lời sẽ phụ thuộc vào ý đồ của bạn. Như ở bài methods mình có trình bày đặc điểm chung của nó đó là không được cached, vì vậy mỗi khi bạn gọi một method thì nó sẽ tính toán lại từ đầu. Còn đối với computed
thì khác, kết quả của các computed sẽ được cached và chỉ cập nhật khi dư liệu thay đổi.
Giả sử mình có chương trình như sau, đây là chương trình chuyển từ số thành chữ:
<div id="example"> <p>Number: "{{ number }}"</p> <p>Number To Word: "{{ showNumberWord }}"</p> </div> <script language="javascript"> var vm = new Vue({ el: '#example', data: { number : "12345" }, computed : { showNumberWord : function(){ console.log("Có gọi"); var message = ""; for (var i = 0; i < this.number.length; i++){ if (this.number[i] == "1"){ message += "Một "; } else if (this.number[i] == "2"){ message += "Hai "; } else if (this.number[i] == "3"){ message += "Ba "; } else if (this.number[i] == "4"){ message += "Bốn "; } else if (this.number[i] == "5"){ message += "Năm "; } else if (this.number[i] == "6"){ message += "Sáu "; } else if (this.number[i] == "7"){ message += "Bảy "; } else if (this.number[i] == "8"){ message += "Tám "; } else if (this.number[i] == "9"){ message += "Chín "; } else if (this.number[i] == "0"){ message += "Không "; } } return message; } } }); </script>
Bạn chú ý là mình có bổ sung đoạn code console.log("Có gọi");
để kiểm tra là computed đó sẽ được gọi bao nhiêu lần. Bây giờ mình sẽ sửa lại ở template như sau:
<div id="example"> <p>Number: "{{ number }}"</p> <p>Number To Word: "{{ showNumberWord }}"</p> <p>Number To Word: "{{ showNumberWord }}"</p> </div>
Nếu theo đúng nguyên tắc của methods thì sẽ có hai tin thông báo "Có gọi", tuy nhiên do đây là một computed nên kết quả ở lần gọi thứ hai được cached nên không có xuất hiện thông báo đó (bạn hãy sử dụng console.log để xem nhé).
3. Computed setter và getter
Mặc định mỗi computed sẽ có hai phương thức đó là getter và setter, nếu bạn không khai báo thì mặc định nó sẽ hiểu là bạn đang sử dụng getter, vì vậy cuối mỗi computed luôn có lệnh return
.
Getter mặc định
<div id="example"> <p>Message: "{{ message }}"</p> <p>Uppercase Message: "{{ uppercaseMessage }}"</p> </div> <script language="javascript"> var vm = new Vue({ el: '#example', data: { message : "Học VueJS tại freetuts.net" }, computed : { uppercaseMessage : function(){ // mặc định Vue sẽ hiểu đây là getter nên phải có return return "[ " + this.message.toUpperCase() + " ]"; } } }); </script>
Khai báo getter
Hoặc bạn cũng có thể sử dụng cú pháp khai báo getter như sau (kết quả bên template cũng không có gì thay đổi):
var vm = new Vue({ el: '#example', data: { message : "Học VueJS tại freetuts.net" }, computed : { uppercaseMessage : { // Khai báo getter get : function(){ return "[ " + this.message.toUpperCase() + " ]"; } } } });
Khai báo setter
Nếu bạn muốn khai báo setter thì viết như sau:
var vm = new Vue({ el: '#example', data: { message : "Học VueJS tại freetuts.net" }, computed : { uppercaseMessage : { // Khai báo getter get : function(){ return "[ " + this.message.toUpperCase() + " ]"; }, // Khai báo setter set : function(newValue){ this.message = newValue.toLowerCase(); } } } }); // Mỗi khi ta thiết lập giá trị cho uppercaseMessage thì message sẽ bị thay đổi // vì nội dung của hàm setter là this.message = newValue.toLowerCase(); vm.uppercaseMessage = "NGUYỄN VAN CƯỜNG"; console.log(vm.message); // nguyễn van cường
Bạn chú ý phần này nhé vì nó hơi khó hiểu. Mỗi khi bạn chạy vm.uppercaseMessage = "giá trị mới";
thì hàm setter sẽ được gọi nên giá trị của message cũng thay đổi theo.
4. Lời kết
Computer khá hay phải không các bạn. Chủ yếu trong bài này bạn phải phân biệt được khi nào thì dùng computed và khi nào thì dùng methods như sau: Nếu một chức năng bạn muốn mỗi khi gọi nó sẽ chạy lại từ đầu thì bạn sẽ dùng methods, còn bạn muốn không cần chạy lại cho tới khi dữ liệu bị thay đổi thì hãy dùng computed.