266
0

Watcher và Computed trong Vue – Section 2 – P3

266
watcher computed vuejs image
Thời gian đọc: 5 phút

Xin chào các bạn, sau phần hai của section 2, mình đã đi sâu hơn về Method cũng như các sự kiện trong vue rồi nhỉ? Thì ở phần 3 này mình sẽ cùng nhau tìm hiểu thêm hai loại keyword nữa là watchercomputed. Kèm theo các viết ngắn gọn của v-on và v-bind bạn nhé.

1/ Sơ lược

Như các bạn cũng đã biết, methods sẽ chứa các function của các bạn. Tuy nhiên, khi các bạn gọi function đó để show kết quả. Thì function đó cũng sẽ chạy theo. Ví dụ, ta hãy cùng nhau tạo một console.log ở function outputNameoutPutCount nhé. Bạn nào chưa có source để test thì các bạn lấy ở bài Section 2 – P2: Event và Methods trong Vue nhé

outputName(){
      console.log('Running Again...');
      return this.name;
},
outPutCount(){
    console.log('Running Count Again...');
    return this.counter;
}
<section id="events">
      <h2>Events in Action</h2>
      <button v-on:click="addCount(5)">Add</button>
      <button v-on:click="counter=counter-1">Remove</button>
      <p v-once>Start from: {{ counter }}</p>
      <p>Result: {{ counter }}</p>
      <input type="text"  id="" v-model="name">
      <p>Your Name: {{ outputName() }}</p>  
</section>

Giờ thì các bạn thử thực hiện thao tác nhập input và check ở phàn console nhé.

Tuy nhiên, có một điều là, methods nó sẽ được gọi lại khi compoment của bạn được render ra. Do đó nó sẽ ảnh hưởng đến performance. Do đó dù các bạn không thao tác bấm addCount mà chỉ nhập input vào, thì function outPutCount vẫn được gọi.
Thì Vue có cung cấp cho các bạn 2 keyword, là watchcomputed, chỉ dùng để xử lý data. Giờ ta cùng tìm hiểu nhé.
Note: các bạn chú ý nhé, ở đây mình có đổi lại từ v-on sang v-model=tên biên. Đây là sự kiện mà vue cung cấp cho input dùng để trực tiếp lấy và thay đổi giá trị

2/ Computed

Computed, giống như method, bên trong nó sẽ là các function. Thì khi này computed, sẽ lưu giá trị ở bộ nhớ cache, chỉ computed data khi và chỉ khi data của function trong computed được thay đổi mà không cần phải tính toán lại như methods.
Dưới đây là mình thay đổi location của function trong methods sang computed.

computed:{
    outputName(){
      console.log('Running Again...');
      return this.name;
    },
    outPutCount(){
      console.log('Running Count Again...');
      return this.counter;
    },
},

Sau đó các bạn gọi tên function trong html.
Note: Tên các bạn gọi function trong computed thì không cần syntax "()" sau tên function đâu nhé. Vì nếu ghi vào nó sẽ hiểu là function trong methods.

<section id="events">
      <h2>Events in Action</h2>
      <button v-on:click="addCount(5)">Add</button>
      <button v-on:click="counter=counter-1">Remove</button>
      <p v-once>Start from: {{ counter }}</p>
      <p>Result: {{ outPutCount }}</p>
      <input type="text"  id="" v-model="name">
      <p>Your Name: {{ outputName }}</p>  
</section>

computed
Dù vậy, computed cũng có một vài hạn chế, như không thể truyền param vào được.
Thì đây là khi ta sẽ tìm đến watcher

3/ Watcher

Watcher, cũng gióng như methods và computed, các bạn sẽ truyền function vào trong đó. Tuy nhiên watcher có sự khác biệt so với hai loại trước. Đó là function bạn phải đặt tên giống như với tên biến trong data. Và tên biến đó phải là biến gây đến sự tác động đến sự thay đổi của biến khác. Tức là biến khác sẽ thay đổi phụ thuộc vào biến tác động nó. Hơi khó hiểu nhỉ? Mình đi vào ví dụ cho dễ hiểu nhé.
Đầu tiên mình sẽ tạo một biến fullName trong data, và sau đó đó tạo methods trong watch.

data() {
    return {
      counter: 10,
      name:'',
      fullName:'',
    };
 },
 watch:{
    name(value){
      this.fullName = value;
      console.log('value:',value);
    }
  },

mình đặt tên function là name = tên mà mình đã tạo trong data và được đặt trong v-model. Do đó nếu name có thay đổi giá trị. Thì fullName sẽ được thay đổi theo. trong đó value trong name chính là giá trị mà name đã được thay đổi.
Vậy giả sử mình có 2 input thì sao?

data() {
    return {
      counter: 10,
      name:'',
      fullName:'',
      lastName:'',
    };
 },
 watch:{
    name(value){
      this.fullName = value + this.lastName;
      console.log('value:',value);
    }
 },
<section id="events">
      <h2>Events in Action</h2>
      <button v-on:click="addCount(5)">Add</button>
      <button v-on:click="counter=counter-1">Remove</button>
      <p v-once>Start from: {{ counter }}</p>
      <p>Result: {{ outPutCount }}</p>
      <input type="text"  id="" v-model="name">
      <input type="text"  id="" v-model="lastName">
      <p>Your Name: {{ fullName }}</p>  
</section>

Và dây là kết quả khi ta truyền vào name và lastName

Sau đó mình sẽ điền thêm vào 1 ký tự trong name

Như các bạn thấy, nó sẽ không cập nhật cùng lúc khi ta nhập vào input name và lastname. Mà nó chỉ cập nhật khi bạn nhập tiếp name một lần nữa. Thì nó mới ra lastName. Vậy ta cần phải làm như sau.

watch:{
    name(value){
      this.fullName = value + this.lastName;
      console.log('value:',value);
    },
    lastName(value){
      this.fullName = this.name + value;
      console.log('last name:',value);
    }
},

Và đây là kết quả:
watcher computed result image
Do đó không như methods và computed. Nó có thể tự dynamic value khi thay đổi giá trị của biến. Nhưng watcher thì các bạn phải tạo action cho biến thứ 2 thì mới dynamic dữ liệu được. Tuy có thua kém về mặt dynamic dữ liệu. Nhưng watcher có khả năng gọi lại giá trị cũ trước đó mà methods và computed không có. Thứ tự sẽ như sau khi các bạn truyền param vào action trong watcher name(newValue,oldValue)
Ví dụ:

watch:{
    name(value,oldValue){
      this.fullName = value + this.lastName;
      console.log('oldValue:',oldValue);
    },
    lastName(value){
      this.fullName = this.name + value;
      console.log('last name:',value);
    }
},

Kết quả:
watcher computed

4/ Shortcode v-bind và v-on

Thông thường nếu các bạn gán value vào attribute của element và gọi function event bằng v-bind:, v-on: đúng chứ? Thì mình sẽ giới thiệu cho các bạn một cách viết ngắn gọn thông qua đoạn code ngắn sau:

Thông thường
<h2 v-bind:att="...">Events in Action</h2>
<button v-on:click="...">Add</button>
Rút gọn
<h2 :att="...">Events in Action</h2>
<button v-on:click="...">Add</button>

5/ Tổng kết

Như vậy mình đã cùng nhau tìm hiểu được về cách viết ngắn gọn của v-bind và v-on. Bên cạnh đó thì ta cũng đã được tìm hiểu thêm hai loại keyword mới là watch và computed. Giờ thì ta cùng nhau so sánh tí nhé Methods vs Computed vs Watch

MethodsComputedWatcher
Sử dụng event binding hoặc data bindingSử dụng data bindingKhông sử dụng các dữ liệu trực tiếp trong template mà thông qua các biến khác
Methods sẽ được gọi sau mỗi lần một trong các compoment được update lạiComputed properties khi có sự thay đổi của propertiesCho phép bạn thực hiện khi có sự thay đổi data gián tiếp
Sử dụng cho cả events hoặc data nếu cần tính toán lại toàn bộSử dụng bất kì cập nhật data nào mà bạn muốn thực hiệnSử dụng cho data này phụ thuộc vào data khác