Props trong Vuejs

Trước khi đến với bài học này nếu bạn chưa nắm vững được components là gì cũng như cách đăng ký components trong Vuejs như nào thì hãy quay lại đọc tài liệu một lần nữa. Ngược lại mời bạn chúng ta cùng tìm hiểu về Props trong Vuejs một attribute khá quan trọng trong Vuejs nhé!

Props là gì?

Props trong Vuejs là một attribute tùy chỉnh dùng để truyền data từ component parent (thành phần cha) đến các component child (thành phần con). Để có thể nhận được dữ liệu từ component parent thì component child phải khai báo prop mà nó mong muốn nhận được từ component parent, bằng cách đặt tên prop ở trong props scope.

Passing Data with Props

Trong Vue.js tất cả các component đều có isolated scope (phạm vi cô lập) riêng. Điều này có nghĩa là chúng ta không thể (và cũng không nên) tham chiếu trực tiếp các dữ liệu ở component cha ( parent ) vào trong component con (child). Mà thay vào đó chúng ta sẽ phải truyền chúng qua props.

Ví dụ:

<div id="app">
    <child message="Hoc.tv"></child>
</div>
<script  type="text/javascript"></script>
<script type="text/javascript">
    Vue.component('child', {
        props: ['message'],
        template: '<h5></h5>',
        
    });
    var app = new Vue({
        el: '#app',
    });
</script>

camelCase vs. kebab-case

Chúng ta đều biết rằng HTML không phân biệt chữ hoa hay chữ thường (ví dụ onclick = OnCliCk), vì vậy cho nên nếu như bạn muốn sự dụng kiểu đặt tên kiểu camelCase cho prop thì ở lúc gọi tới componet bạn phải chuyển đối nó về kebad-case.

Ví dụ:

<div id="app">
    <child my-say="Hoc.tv -  Học học nữa học mãi"></child>
</div>
<script  type="text/javascript"></script>
<script type="text/javascript">
    Vue.component('child', {
        props: ['mySay'],
        template: '<h5></h5>',

    });
    var app = new Vue({
        el: '#app',
    });
</script>

Dynamic Props

Tương tự như đối với attribute, chúng ta cũng có thể sử dụng v-bind để ràng buộc prop data trên cấp cha . Điều đó có nghĩa là khi dữ liệu ở cấp cha thay đổi thì cấp con cũng thay đổi theo.

Ví dụ:

<div id="app">
    <p>
        <input type="text" v-model="message">
    </p>
    <child v-bind:my-say="message"></child>
    <!-- hoặc bạn cũng có thể sử dụng cú pháp thu gọn là
        :my-say="message"
     -->
</div>
<script  type="text/javascript"></script>
<script type="text/javascript">
    Vue.component('child', {
        props: ['mySay'],
        template: '<h5></h5>',

    });
    var app = new Vue({
        el: '#app',
        data: {
            message : null
        }
    });
</script>

Literal vs Dynamic

Nếu như bạn muốn truyền dữ liệu dạng số (number) vào component thì bạn sẽ phải sử dụng v-bind, còn nếu bạn dùng prop thông thường thì nó sẽ nhận là string. Hãy xem ví dụ dưới đây để kiểm chứng:

<div id="app">
        <child my-say="1"></child>
        <child v-bind:my-say="1"></child>
    </div>
    <script src="https://unpkg.com/vue@2.4.2" type="text/javascript"></script>
    <script type="text/javascript">
        Vue.component('child', {
            props: ['mySay'],
            template: '<h1>{{ typeof(mySay) }}</h1>',

        });
        var app = new Vue({
            el: '#app',
        });
</script>

Chạy Code

One-Way Data Flow

Các props trong Vue.js đều là one-way-down nó dùng để binding data giữa cấp cha và cấp con. Điều đó có nghĩa là khi dữ liệu ở cấp cha thay đổi thì nó sẽ được binding xuống cấp con. Ngoài ra nếu như dữ liệu ở cấp cha (component parent) thay đổi thì cấp con (component child) sẽ cập nhật và lấy giá trị mới nhất của dữ liệu thay đổi đó. Và đúng như cái tên one-way-down bạn không thể thay đổi một prop bên trong component con. Nếu như bạn cố tình thực hiện điều đó, thì Vue.js sẽ đưa ra cảnh báo cho bạn ở trong console.

Đừng lo lắng bởi vì trong Vuejs chúng ta có thể thay đổi nó một cách gián tiếp bằng 2 cách sau:

Cách 1: Khởi tạo một data scope chứa prop đó, từ đó bạn có thể thay đổi dữ liệu thông qua data scope.

Ví dụ:

<div id="app">
    <child my-say="Xin chào!"></child>
</div>
<script  type="text/javascript"></script>
<script type="text/javascript">
    Vue.component('child', {
        props: ['mySay'],
        data : function () {
            return { dataSay : this.mySay + " This is dataSay!"};
        },
        template: '<h5></h5>',


    });
    var app = new Vue({
        el: '#app',
    });
</script>

Cách 2: Đề xuất prop như một dữ liệu cần được thay đổi.

Vú dị:

<div id="app">
    <child my-say="Xin chào!"></child>
</div>
<script  type="text/javascript"></script>
 <script type="text/javascript">
        Vue.component('child', {
            props: ['mySay'],
            computed : {
                convertSay: function () {
                    return this.mySay.trim().toUpperCase();
                }
            },
            template: '<h5>{{ convertSay }}</h5>',
        });
        var app = new Vue({
            el: '#app'
        });
</script>

Prop Validation

Nếu bạn muốn ràng buộc kiểu dữ liệu của một prop, hoặc là xác định giá trị mặc định của nó thid Vue.js cũng hỗ trợ bạn điều đó.

Cú pháp xác định kiểu dữ liệu:

props: {
  propName: typeName
}

hoặc

props: {
  propName: [typeName1,typeName2,...typeNamen]
}

hoặc

props: {
  propName: {
    type: typeName
  }
}

Trong đó:

  • propName là tên của prop mà bạn muốn ràng buộc.
  • typeName là kiểu dữ liệu bạn muốn xác định. Các kiểu dữ liệu gồm có:
    • String
    • Number
    • Boolean
    • Function
    • Object
    • Array
    • Symbol

Ví dụ:

Vue.component('ex',{
    props: {
        name: String,


        class: [Number, String],
        
        point: {
            type: Number
        }
    }
});

Bạn cũng có thể tự custom validate cho riêng mình bằng cách sử dụng validator key trong object của prop bạn cần ràng buộc.

Ví dụ:

Vue.component('ex',{
    props: {
        point: {
            validator: function (value) {
                return value > 10;
            }
        }
    }
});

Và bạn cũng có thể thiết lập giá trị mặc định cho prop bằng default scope.

Vue.component('ex',{
    props: {
        point: {
            type: Number,
            default: 5,
        }
    }
});

Nếu muốn prop bắt buộc phải là required thì chúng ta cần thiết lập required scope thành true

Vue.component('ex',{
    props: {
        point: {
            type: Number,
            required: true,
        }
    }
});
Lưu ý:
  • Vue.js sẽ thông báo cho bạn ở cửa sổ console nếu như dữ liệu validate không qua trong khi bạn đang mode chương trình ở chế độ development
  • Dữ liệu trong default scope hay trong validator scope phải là dữ liệu đã có sẵn (không dùng được dữ liệu của data, computed, methods) vì validate sẽ được thực hiện trước khi component instance.

2. Non-Prop Attributes.

Non-Prop attribute trong Vuejs là một attribute được chuyển đến component, nhưng nó sẽ không có được tính chất prop đã định nghĩa.

Mặc dù các prop đã được xác định rõ ràng để chuyển thông tin đến child component thế nhưng ngay cả chính tác giả của thư viện component trong Vue.js cũng không thể lường trước được bối cảnh của người sử dụng vì vậy component cho phép chúng ta xác định bất kỳ một attribute nào cũng có thể được xác định trên component parent.

3. x-template.

Trong các phần trước chúng ta được hướng dẫn khai báo template bằng cách khai báo nó ở trong template scope rồi, thế nhưng sẽ ra sao nếu template phức tạp hơn nhiều chúng ta tưởng tượng không chỉ là 1 hay 2 dòng code nữa. May mắn thay Vue.js cũng cung cấp cho chúng ta khai báo template ở trong cặp thẻ script có type là x-template. Với cú pháp như sau:

<script type="text/x-template" id="template-id">
    //content template
</script>

Trong cú pháp này chúng ta cần xác định id cho template để có thể gọi nó ở trong component template. Đồng thời ở trong template scope chúng ta cũng cần xác định id của x-template. Với cú pháp:

Vue.component('component-tag', {
    template: '#template-id'
});

Vú dị minh họa:

<div id="app">
    <child></child>
</div>
<script type="text/x-template" id="h5-template">
    <h5>Template được khai báo trong x-template</h5>
</script>
<script  type="text/javascript"></script>
<script type="text/javascript">
    Vue.component('child', {
        template: '#h5-template'
    });
    var app = new Vue({
        el: '#app',
    });
</script>

4. Tổng kết

Vậy là chúng ta sắp đi đến những bước cuối cùng trong việc tìm hiểu về component rồi đấy các bạn ạ. Hi vọng sau bài viết này các bạn đã hiểu được Props trong Vuejs là gì và cách sử dụng Props trong Vuejs. Chúc các bạn thành công!

Bình luận