Component trong Vue.js

Trong bài viết này chúng ta sẽ tiếp tục tìm hiểu một  tính năng mạnh mẽ nhất của Vuejs đó chính là Component trong Vuejs. Vậy Component là gì chúng ta sẽ tìm hiểu về nó ngay sau đây nhé

Component dịch ra tiếng Việt có nghĩa là thành phần thế nhưng trong khuôn khổ của loạt bài học này chúng ta sẽ giữ nguyên từ Component bởi vì đây là thuật ngữ được sử dụng nhiều trong Vue.

1. Component là gì?

Component là một trong các tính năng mạnh mẽ nhất của Vue.js. Component trong vuejs giúp cho chúng ta gom nhóm các mã HTML lại để tái sử dụng cho các module tương tự. 

Ở mức nâng cao thì component là một thành phần được Vue.js biên dịch để xử lý các hành vi. Và trong một vài trường hợp thì nó cũng có thể xuất hiện như một phần tử HTML với các attribute đặc biệt (is - sẽ nói ở bên dưới).

Một component trong Vue về bản chất là một đối tượng Vue với các tùy chọn cho trước. Để dễ hình dung những ứng dụng quy mô lớn trong Vue đều được tạo thành từ những phần tử nhỏ độc lập và thường được tái sử dụng, các phần tử đó gọi là component. Nếu bạn để ý, gần như bất kì một loại giao diện ứng dụng nào cũng có thể được trừu tượng hóa thành một tập hợp dạng cây của các phần tử con. Một hệ thống các component góp phần tạo thành 1 cây ứng dụng trong Vue.


2. Using Components.

Registration

Trong Vue.js để khai báo một component ở mức độ global thì chúng ta sử dụng cú pháp:

Vue.component('tag', options);

Trong đó:

  • tag là tên mà bạn muốn gán cho component đó.
  • options là một object chứa các tham số là template hay dữ liệu kèm theo.

Lưu ý: Vue.js không thực thi các quy tắc của W3C cho tên của các component tag (tất cả đều là chữ thường, và phải có dấu nối giữa các từ) mặc dù theo như nhận xét thì chuẩn này tốt.

VD: Mình sẽ đăng ký một component và gọi nó luôn ở trong ứng dụng.

<div id="app">
<tdc-component></tdc-component>
</div>
<script  type="text/javascript"></script> <script type="text/javascript">
   //đăng ký component    
    Vue.component('tdc-component',{
        template: '<h5>Chào mừng bạn đến với website Hoc.tv</h5>'});    
    var app = new Vue({
        el: '#app',
    }); 
</script>

Local Registration

Nếu như bạn không muốn đăng ký một component ở trạng thái global nữa thì bạn cũng có thể đăng ký nó ở một phạm vi sử dụng nào đó (Vue.js gọi đó là local) thì bạn cũng có thể khai báo nó trong Vue instance.

Ví dụ:  Chuyển component ở ví dụ trên về trạng thái local.

<div id="app">
    <tdc-component></tdc-component>
</div>
<script  type="text/javascript"></script>
<script type="text/javascript">
    var app = new Vue({
        el: '#app',
        components: {
            'tdc-component': {
                template : '<h5>Chào mừng bạn đến với website Hoc.tv</h5>'
            }
        }
    });
</script>
Chạy Code hoặc bạn cũng có thể khai báo như sau cho dễ nhìn.
<div id="app">
<tdc-component></tdc-component>
</div>
<script  type="text/javascript"></script>
<script type="text/javascript">
       var temp = {
                  template : '<h5>Chào mừng bạn đến với website Hoc.tv</h5>'
       }; 
       var app = new Vue({
                 el: '#app',
                 components: {
                             'tdc-component': temp
                              }
       });
</script>

DOM Template Parsing Caveats.

Trong trường hợp chúng ta muốn sử dụng DOM như các template, thì chúng ta sẽ phải tuân thủ theo 1 số các hạn chế lên quan đến cách hoạt động của HTML. Bởi Vue.js sẽ chỉ có thể truy xuất được nội dung khi mà trình duyệt đã xử lý và làm chuẩn hóa chúng (ở đây là các thẻ HTML). Điển hình như các tag ul, ol, table ,...

VD: Như khi chúng ta sử dụng các tr trong table.

<div id="app">
    <table>
        <tdc-component></tdc-component>
    </table>
</div>
<script  type="text/javascript"></script>
<script type="text/javascript">
    var temp = {
        template : '<tr>Học Vuejs tại Hoc.tv</tr>'
    };
    var app = new Vue({
        el: '#app',
        components: {
            'tdc-component': temp
        }
    });
</script>

Theo dõi phần Result để xem kết quả:

Dễ dàng nhận thấy kết quả hiển thị sai ko có bảng nào hiện ra cả mà hiện mã HTML như sau:

<tr>Học Vuejs tại Hoc.tv</tr>
<table></table>

Để khắc phục vấn đề trên thì chúng ta sẽ sử dụng is như một attribute của HTML để bind component vào nó.

VD: Khắc phục ví dụ trên.

<div id="app">
    <table>
        <tr is="tdc-component"></tr>
    </table>
</div>
<script  type="text/javascript"></script>
<script type="text/javascript">
    var temp = {
        template : '<tr>Học Vuejs tại Hoc.tv</tr>'
    };
    var app = new Vue({
        el: '#app',
        components: {
            'tdc-component': temp
        }
    });
</script>
Chạy Code thì trình duyệt đã render ra cho chúng ta kết đúng:


<table>
<tbody>
<tr>Học Vuejs tại Hoc.tv</tr>
</tbody>
</table>

Thế nhưng không phải chuyện gì cũng hoàn hảo Vue.js  sẽ không khắc phục được nếu như bạn sử dụng template ở các trường hợp sau:

  • <script type="text/x-template">
  • Javascript inline string.
  • .vue component.

Data must be a function

Trong Vue instance data scope là một object còn trong Component  thì data scope phải là 1 function. Nếu bạn cố gắng sử dụng data như một object thì Vue sẽ cảnh báo và khuyên bạn nên khái báo data là một hàm.

Đối với trường hợp data là hàm thì chúng ta cũng sử dụng tương tự như với object.

VD:

<div id="app">
    <tdc-component></tdc-component>
</div>
<script  type="text/javascript"></script>
<script type="text/javascript">
    var data = {
        message: 'Hoc.tv'
    };
    Vue.component('tdc-component', {
        template: '<h1></h1>',
        data: function() {
            return data;
        }
    });
    var app = new Vue({
        el: '#app'
    });
</script>

Ví dụ: Trường hợp gọi một component nhiều lần.

<div id="app">
    <tdc-component></tdc-component>
    <tdc-component></tdc-component>
    <tdc-component></tdc-component>
</div>
<script  type="text/javascript"></script>
<script type="text/javascript">
    var data = {
        count : 0
    };
    Vue.component('tdc-component', {
        template: '<button v-on:click="count += 1"></button>',
        data: function() {
            return data;
        }
    });
    var app = new Vue({
        el: '#app'
    });
</script>
Chạy Code

Kiểm tra kết quả chúng ta sẽ thấy sau khi thử nhấn vào bất kỳ 1 nút nào thì cả 3 nút đều thay đổi. Lý do là do khai báo data ở trạng thái global nên khi tác động thì nó sẽ tác động đến cả 3 button. Để khắc phục điều đó thì chúng ta chỉ cần chuyển nó về dạng local là được.

<div id="app">
    <tdc-component></tdc-component>
    <tdc-component></tdc-component>
    <tdc-component></tdc-component>
</div>
<script  type="text/javascript"></script>
<script type="text/javascript">
    Vue.component('tdc-component', {
        template: '<button v-on:click="count += 1"></button>',
        data: function() {
            return { count : 0 };
        }
    });
    var app = new Vue({
        el: '#app'
    });
</script>

Kiểm tra lại kết quả 

Composing components

Một trong những tính năng hay của  của omposing components trong Vue.js là  các component được sử dụng cùng nhau và có thể có mối quan hệ khăng khít với nhau. Tà thông thường nhất các bạn có thể nhìn thấy là mối quan hệ parent-child (cha con) tức là  "Component A có thể sử dụng được componet B ở trong template của riêng nó, và nó không nhất thiết cần phải giao tiếp với nhau mà vẫn có thể gửi thông điệp cho nhau được".

Ví dụ minh họa:

Vue.component('component-a', {
    template: '<font v-bind:color="color">Hoc.tv</font>',
    data: function () {
        return { color: "magenta" }
    }
});
Vue.component('component-b', {
    template: '<h5><component-a></component-a></h5>',
});
var app = new Vue({
    el: '#app'
});

Tuy nhiên, để tiện cho việc bảo trì và tái sử dụng lại component chúng ta nên tách nó ra các interface khác nhau. Cụ thể trong Vue.js nó có thể được tóm gọn lại như props down hay events up - parent truyền props cho child và child phản hồi lại cho parent bằng event.

  • Component cha truyền Props cho component con
  • Component con phản hồi lại cho Component cha bằng Event

Bạn có thể tham khảo mô hình sau để hiểu hơn về nó.


Qua bài viết này chắc hẳn các bạn đã có được cái nhìn tổng quan về component và áp dụng nó vào trong các dự án của riêng mình rồi phải không nào. Chi tiết hơn về component trong Vue.js chúng ta sẽ tìm hiểu trong bài sau nhé. Hẹn gặp lại các bạn!

Bình luận