đạo cụ Vue
Props là một tùy chọn cấu hình trong Vue.
Với đạo cụ, chúng ta có thể truyền dữ liệu đến các thành phần thông qua các thuộc tính tùy chỉnh cho thẻ thành phần.
Truyền dữ liệu tới một thành phần
Bạn có nhớ ví dụ ở trang trước trong đó cả ba thành phần đều nói 'Apple' không? Với đạo cụ, giờ đây chúng ta có thể truyền dữ liệu xuống các thành phần của mình để cung cấp cho chúng nội dung khác nhau và làm cho chúng trông khác biệt.
Hãy tạo một trang đơn giản để hiển thị 'Táo', 'Pizza' và 'Gạo'.
Trong tệp ứng dụng chính App.vue
chúng ta tạo thuộc tính 'food-name' của riêng mình để truyền prop với các thẻ thành phần <food-item/>
:
App.vue
:
<template>
<h1>Food</h1>
<food-item food-name="Apples"/>
<food-item food-name="Pizza"/>
<food-item food-name="Rice"/>
</template>
<script></script>
<style>
#app > div {
border: dashed black 1px;
display: inline-block;
width: 120px;
margin: 10px;
padding: 10px;
background-color: lightgreen;
}
</style>
Nhận dữ liệu bên trong một thành phần
Để nhận dữ liệu được gửi qua thuộc tính 'food-item' từ App.vue
chúng tôi sử dụng tùy chọn cấu hình 'props' mới này. Chúng tôi liệt kê các thuộc tính nhận được để tệp thành phần *.vue của chúng tôi biết về chúng và bây giờ chúng tôi có thể sử dụng các đạo cụ ở bất cứ đâu chúng tôi muốn giống như cách chúng tôi sử dụng thuộc tính dữ liệu.
FoodItem.vue
:
<script>
export default {
props: [
'foodName'
]
}
</script>
Thuộc tính props được viết bằng dấu gạch ngang -
để phân tách các từ (kebab-case) trong thẻ <template>
, nhưng kebab-case không hợp pháp trong JavaScript. Vì vậy, thay vào đó chúng ta cần viết tên thuộc tính dưới dạng CamelCase trong JavaScript và Vue sẽ tự động hiểu điều này!
Cuối cùng, ví dụ của chúng tôi với các phần tử <div>
cho 'Táo', 'Pizza' và 'Gạo' trông như thế này:
Ví dụ
App.vue
:
<template>
<h1>Food</h1>
<food-item food-name="Apples"/>
<food-item food-name="Pizza"/>
<food-item food-name="Rice"/>
</template>
FoodItem.vue
:
<template>
<div>
<h2>{{ foodName }}</h2>
</div>
</template>
<script>
export default {
props: [
' foodName '
]
}
</script>
<style></style>
Chạy ví dụ » Chúng ta sẽ sớm biết cách chuyển các loại dữ liệu khác nhau dưới dạng thuộc tính props cho các thành phần, nhưng trước khi làm điều đó, hãy mở rộng mã của chúng ta bằng phần mô tả về từng loại thực phẩm và đặt các phần tử <div>
thực phẩm bên trong một trình bao bọc Flexbox.
Ví dụ
App.vue
:
<template>
<h1>Food</h1>
<div id="wrapper">
<food-item
food-name="Apples"
food-desc="Apples are a type of fruit that grow on trees."/>
<food-item
food-name="Pizza"
food-desc="Pizza has a bread base with tomato sauce, cheese, and toppings on top."/>
<food-item
food-name="Rice"
food-desc="Rice is a type of grain that people like to eat."/>
</div>
</template>
<script></script>
<style>
#wrapper {
display: flex;
flex-wrap: wrap;
}
#wrapper > div {
border: dashed black 1px;
margin: 10px;
padding: 10px;
background-color: lightgreen;
}
</style>
FoodItem.vue
:
<template>
<div>
<h2>{{ foodName }}</h2>
<p>{{ foodDesc }}</p>
</div>
</template>
<script>
export default {
props: [
'foodName',
'foodDesc'
]
}
</script>
<style></style>
Chạy ví dụ »Đạo cụ Boolean
Chúng tôi có thể đạt được các chức năng khác nhau bằng cách chuyển các props của các loại dữ liệu khác nhau và chúng tôi có thể xác định các quy tắc về cách cung cấp các thuộc tính khi các thành phần được tạo từ App.vue
.
Hãy thêm một chỗ dựa mới 'isFavorite'. Đây phải là một giá trị boolean có giá trị true
hoặc false
để chúng ta có thể sử dụng trực tiếp với v-show
để hiển thị thẻ tem yêu thích <img>
nếu món ăn được coi là món ăn được yêu thích.
Để truyền props có kiểu dữ liệu khác với String, chúng ta phải viết v-bind:
trước thuộc tính mà chúng ta muốn truyền.
Đây là cách chúng tôi chuyển prop boolean 'isFavorite' từ App.vue
dưới dạng thuộc tính 'is-favorite':
App.vue
:
<template>
<h1>Food</h1>
<p>My favorite food has a diploma image attached to it.</p>
<div id="wrapper">
<food-item
food-name="Apples"
food-desc="Apples are a type of fruit that grow on trees."
v-bind:is-favorite="true"/>
<food-item
food-name="Pizza"
food-desc="Pizza has a bread base with tomato sauce, cheese, and toppings on top."
v-bind:is-favorite="false"/>
<food-item
food-name="Rice"
food-desc="Rice is a type of grain that people like to eat."
v-bind:is-favorite="false"/>
</div>
</template>
Chúng tôi nhận được giá trị boolean 'isFavorite' bên trong FoodItem.vue
và hiển thị tem yêu thích nếu món ăn được coi là yêu thích:
Ví dụ
FoodItem.vue
:
<template>
<div>
<h2>
{{ foodName }}
<img src="/img_quality.svg" v-show="isFavorite">
</h2>
<p>{{ foodDesc }}</p>
</div>
</template>
<script>
export default {
props: ['foodName','foodDesc','isFavorite']
}
</script>
<style>
img {
height: 1.5em;
float: right;
}
</style>
Chạy ví dụ »Hình ảnh: Để làm cho hình ảnh trong ví dụ trên hoạt động cục bộ trong dự án trên máy của bạn, hãy mở ví dụ trên, nhấp chuột phải vào hình ảnh, chọn "Save Image As..." và lưu nó vào thư mục "public" trong dự án của bạn .
Giao diện đạo cụ
Trong ví dụ trên, dựa trên mã bên trong FoodItem.vue
, chúng tôi không thể biết chắc chắn rằng mình nhận được prop 'isFavorite' và chúng tôi không thể biết chắc liệu đó có phải là giá trị boolean hay không. Để giúp chúng tôi thực hiện điều này, chúng tôi có thể xác định loại dữ liệu của đạo cụ mà chúng tôi nhận được, chúng tôi có thể đặt đạo cụ là bắt buộc và thậm chí chúng tôi có thể tạo các hàm xác thực để xác thực các đạo cụ mà chúng tôi nhận được.
Việc xác định các đạo cụ mà chúng tôi nhận được sẽ đóng vai trò là tài liệu cho những người khác nếu bạn làm việc theo nhóm và nó cung cấp cho chúng tôi các cảnh báo trong bảng điều khiển nếu các quy tắc mà chúng tôi đã xác định bị vi phạm.
Đạo cụ như một đối tượng
Trong FoodItem.vue
, chúng tôi nhận xét cách chúng tôi xác định các props trong một mảng để lấy nó làm tham chiếu và thay vào đó xác định các props trong một đối tượng. Chúng ta cũng có thể xác định kiểu dữ liệu của từng prop ngoài tên prop, như sau:
FoodItem.vue
:
<script>
export default {
// props: ['foodName','foodDesc','isFavorite']
props: {
foodName: String,
foodDesc: String,
isFavorite: Boolean
}
}
</script>
Với các đạo cụ được xác định theo cách này, những người khác có thể nhìn vào bên trong FoodItem.vue
và dễ dàng xem thành phần đó mong đợi điều gì.
Nếu một thành phần được tạo từ phần tử gốc (trong trường hợp của chúng ta là App.vue
) và được cấp một prop có kiểu dữ liệu sai, bạn sẽ nhận được cảnh báo trong bảng điều khiển, như sau:
Những cảnh báo như vậy rất hữu ích để chúng tôi và những người khác biết rằng một thành phần không được sử dụng như mong muốn và cho biết điều gì sai để chúng tôi có thể sửa lỗi.
Đạo cụ bắt buộc
Để nói với Vue rằng cần có prop, chúng ta cần xác định prop là một đối tượng. Hãy tạo prop 'foodName' theo yêu cầu, như thế này:
FoodItem.vue
:
<script>
export default {
// props: ['foodName','foodDesc','isFavorite']
props: {
foodName: {
type: String,
required: true
},
foodDesc: String,
isFavorite: Boolean
}
}
</script>
Nếu một thành phần được tạo từ phần tử gốc (trong trường hợp của chúng tôi là App.vue
) và một prop bắt buộc không được xác định, bạn sẽ nhận được cảnh báo trong bảng điều khiển, như sau:
Những cảnh báo như vậy rất hữu ích để chúng tôi và những người khác biết rằng một thành phần không được sử dụng như mong muốn và cho biết điều gì sai để chúng tôi có thể sửa lỗi.
Giá trị mặc định
Chúng ta có thể đặt giá trị mặc định cho prop.
Hãy tạo một giá trị mặc định cho prop 'foodDesc' trong thành phần 'FoodItem', sau đó tạo một mục như vậy cho gạo mà không cần xác định prop 'foodDesc':
Ví dụ
App.vue
:
<template>
<h1>Food</h1>
<p>My favorite food has a diploma image attached to it.</p>
<div id="wrapper">
<food-item
food-name="Apples"
food-desc="Apples are a type of fruit that grow on trees."
v-bind:is-favorite="true"/>
<food-item
food-name="Pizza"
food-desc="Pizza has a bread base with tomato sauce, cheese, and toppings on top."
v-bind:is-favorite="false"/>
<food-item
food-name="Rice"
food-desc="Rice is a type of grain that people like to eat."
v-bind:is-favorite="false"/>
</div>
</template>
FoodItem.vue
:
<script>
export default {
props: {
foodName: {
type: String,
required: true
},
foodDesc: {
type: String,
required: false,
default: 'This is the default description.'
}
isFavorite: {
type: Boolean,
required: false,
default: false
}
}
}
</script>
Chạy ví dụ »Chức năng xác thực đạo cụ
Chúng ta cũng có thể định nghĩa một hàm xác thực để quyết định xem giá trị prop có hợp lệ hay không.
Các hàm xác thực như vậy phải trả về đúng hoặc sai. Khi trình xác nhận trả về sai, điều đó có nghĩa là giá trị prop không hợp lệ. Giá trị prop không hợp lệ sẽ tạo ra cảnh báo trong bảng điều khiển trình duyệt khi chúng tôi chạy trang của mình ở chế độ nhà phát triển và cảnh báo là gợi ý hữu ích để đảm bảo các thành phần được sử dụng như dự định.
Giả sử chúng ta muốn mô tả món ăn có độ dài nhất định, từ 20 đến 50 ký tự. Chúng ta có thể thêm chức năng xác thực để đảm bảo mô tả thực phẩm được cung cấp có độ dài hợp lệ.
FoodItem.vue
:
<script>
export default {
props: {
foodName: {
type: String,
required: true
},
foodDesc: {
type: String,
required: false,
default: 'This is the default description.',
validator: function(value) {
if( 20<value.length && value.length<50 ) {
return true;
}
else {
return false;
}
}
}
isFavorite: {
type: Boolean,
required: false,
default: false
}
}
}
</script>
Lưu ý: Nếu bạn thêm mã trình xác thực ở trên vào dự án cục bộ của mình, bạn sẽ nhận được cảnh báo ở chế độ phát triển vì mô tả món ăn cho pizza có 65 ký tự, dài hơn 15 ký tự so với chức năng xác thực cho phép.
Sửa đổi đạo cụ
Khi một thành phần được tạo trong phần tử cha, chúng ta không được phép thay đổi giá trị của prop nhận được trong phần tử con. Vì vậy bên trong FoodItem.vue
chúng ta không thể thay đổi giá trị của prop 'isFavorite' mà chúng ta nhận được từ App.vue
. Prop ở chế độ chỉ đọc từ cha mẹ, đó là App.vue
trong trường hợp của chúng tôi.
Nhưng giả sử chúng tôi muốn người dùng có thể thay đổi món ăn nào được coi là yêu thích bằng cách nhấp vào nút. Bây giờ cần phải thay đổi prop 'isFavorite', nhưng chúng ta không thể làm điều đó vì nó chỉ được đọc.
Chúng tôi không được phép thay đổi 'isFavorite'. Điều này sẽ tạo ra một lỗi.
methods: {
toggleFavorite() {
this.isFavorite = !this.isFavorite;
}
}
Để giải quyết vấn đề này, chúng ta có thể sử dụng prop để khởi tạo giá trị dữ liệu mới 'foodIsFavorite', bên trong FoodItem.vue
, như thế này:
data() {
return {
foodIsFavorite: this.isFavorite
}
}
Và bây giờ chúng ta có thể thêm một phương thức để người dùng có thể chuyển đổi giá trị dữ liệu mới này:
methods: {
toggleFavorite() {
this.foodIsFavorite = !this.foodIsFavorite;
}
}
Chúng ta cũng phải thêm nút chuyển đổi cho từng mặt hàng thực phẩm và thay đổi v-show
trong thẻ <img>
để phụ thuộc vào thuộc tính dữ liệu mới 'foodIsFavorite'. Và để làm cho ví dụ của chúng ta đơn giản hơn, chúng ta cũng thu gọn phần khai báo props thành một mảng.
Ví dụ
FoodItem.vue
:
<template>
<div>
<h2>
{{ foodName }}
<img src="/img_quality.svg" v-show="foodIsFavorite">
</h2>
<p>{{ foodDesc }}</p>
<button v-on:click="toggleFavorite">Favorite</button>
</div>
</template>
<script>
export default {
props: ['foodName','foodDesc','isFavorite'],
data() {
return {
foodIsFavorite: this.isFavorite
}
},
methods: {
toggleFavorite() {
this.foodIsFavorite = !this.foodIsFavorite;
}
}
}
</script>
<style>
img {
height: 1.5em;
float: right;
}
</style>
Chạy ví dụ »