VueJS – Reactivity

Reactivity có thể được dịch là tương phản. Trong VueJS mỗi khi dữ liệu thay đổi, View sẽ được cập nhật lại điều đó có nghĩa là VueJS sẽ giám sát chúng và thực hiện khi có thay đổi. Các bạn cũng đã sử dụng đến reactivity nhiều lần thông qua các ví dụ gán dữ liệu 2 chiều (two-way data binding), tăng giá trị khi click….

Chúng ta xem xét ví dụ sau

Ví dụ

<html>
   <head>
      <title>VueJs Instance</title>
      <script type = "text/javascript" src = "https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
   </head>
   <body>
      <div id = "app">
         <p style = "font-size:25px;">Counter: {{ counter }}</p>
         <button @click = "counter++" style = "font-size:25px;">Click Me</button>
      </div>
      <script type = "text/javascript">
         var vm = new Vue({
            el: '#app',
            data: {
               counter: 1
            }
         });
         vm.$watch('counter', function(nval, oval) {
            alert('Counter is incremented :' + oval + ' to ' + nval + '!');
         });
         setTimeout(
            function(){
               vm.counter = 20;
            },2000
         );
      </script>
   </body>
</html>

Trong ví dụ này, chúng ta tạo counter trong data có giá trị mặc định là 1. Khi click button nó sẽ cộng thêm 1. Và 1 function sẽ thay đổi giá trị nó thành 20 sau 2s.

Để thông báo khi có sự thay đổi, chúng ta dùng $watch, và mình sẽ dùng $watch bên ngoài vue instance. Khi có bất kỳ sự thay đổi nào của counter nó sẽ alert ra cho chúng ta thông báo giá trị cũ và mới.

Kết quả

Sau 2 giây, giá trị mặc định sẽ được thay đổi thành 20.

Trường hợp chúng ta click để tăng 1, giá trị nó sẽ thay đổi từ 2 đến 20.

Như vậy VueJS có thể giám sát các giá trị khi đã khai báo. Tuy nhiên trong các trường hợp chúng ta thêm hay xóa các thuộc tính thì VueJS không thể giám sát được chúng. Lúc này chúng ta cần sử dụng phương thức Vue.set, Vue.delete.

Vue.set

Phương thức Vue.set giúp Vue có thể giám sát các giá trị đưa vào.

Cấu trúc

Vue.set( target, key, value )
  • target : là mảng hay object.
  • key : number hay string.
  • value : bất kỳ kiểu dữ liệu nào.

Ví dụ

<html>
   <head>
      <title>VueJs Instance</title>
      <script type = "text/javascript" src = "https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
   </head>
   <body>
      <div id = "app">
         <p style = "font-size:25px;">Counter: {{ products.id }}</p>
         <button @click = "products.id++" style = "font-size:25px;">Click Me</button>
      </div>
      <script type = "text/javascript">
         var myproduct = {"id":1, name:"book", "price":"20.00"};
         var vm = new Vue({
            el: '#app',
            data: {
               counter: 1,
               products: myproduct
            }
         });
         vm.products.qty = "1";
         console.log(vm);
         vm.$watch('counter', function(nval, oval) {
            alert('Counter is incremented :' + oval + ' to ' + nval + '!');
         });
      </script>
   </body>
</html>

Trong ví dụ này chúng ta có object myproduct gồm id, name, price. Và chúng ta tạo Vue instance với data có productsmyproduct. Sau khi tạo Vue instance với data đó, chúng ta mới thêm thuộc tính qty vào object myproduct.

vm.products.qty = "1";

Và kết quả

Phương thức get/set chỉ có ở những thuộc tính trong data lúc khởi tạo Vue instance (id, name, price) và không có ở qty. Nghĩa là Vue không thể giám sát được sự thay đổi của giá trị qty này.

Trong trường hợp này để VueJS có thể giám sát giá trị thuộc tính sau khi khởi tạo Vue instance chúng ta sử dụng Vue.set.

Vue.set(myproduct, 'qty', 1);

Ví dụ

<html>
   <head>
      <title>VueJs Instance</title>
      <script type = "text/javascript" src = "https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
   </head>
   <body>
      <div id = "app">
         <p style = "font-size:25px;">Counter: {{ products.id }}</p>
         <button @click = "products.id++" style = "font-size:25px;">Click Me</button>
      </div>
      <script type = "text/javascript">
         var myproduct = {"id":1, name:"book", "price":"20.00"};
         var vm = new Vue({
            el: '#app',
            data: {
               counter: 1,
               products: myproduct
            }
         });
         Vue.set(myproduct, 'qty', 1);
         console.log(vm);
         vm.$watch('counter', function(nval, oval) {
            alert('Counter is incremented :' + oval + ' to ' + nval + '!');
         });
      </script>
   </body>
</html>

Bây giờ chúng ta đã thấy phương thức get/set xuất hiện ở thuộc tính qtyVue có thể giám sát nó.

Vue.delete

Phương thức này dùng để xóa thuộc tính.

Cấu trúc

Vue.delete( target, key )

Trong đó

  • target: Có thể là object hay array.
  • key: Có thể là string hay number.

Ví dụ

<html>
   <head>
      <title>VueJs Instance</title>
      <script type = "text/javascript" src = "https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
   </head>
   <body>
      <div id = "app">
         <p style = "font-size:25px;">Counter: {{ products.id }}</p>
         <button @click = "products.id++" style = "font-size:25px;">Click Me</button>
      </div>
      <script type = "text/javascript">
         var myproduct = {"id":1, name:"book", "price":"20.00"};
         var vm = new Vue({
            el: '#app',
            data: {
               counter: 1,
               products: myproduct
            }
         });
         Vue.delete(myproduct, 'price');
         console.log(vm);
         vm.$watch('counter', function(nval, oval) {
            alert('Counter is incremented :' + oval + ' to ' + nval + '!');
         });
      </script>
   </body>
</html>

Trong ví dụ này chúng ta đã xóa thuộc tính price.

Vue.delete(myproduct, 'price');

Kết quả

Chỉ còn 2 thuộc tính idname trong Object products còn price đã được xóa. Cả set/get của nó cũng không còn.