Phương thức Vue $emit()
Với phương thức $emit()
tích hợp trong Vue, chúng ta có thể tạo một sự kiện tùy chỉnh trong thành phần con có thể được ghi lại trong thành phần cha.
Props được sử dụng để gửi dữ liệu từ phần tử cha đến thành phần con và $emit()
được sử dụng để thực hiện điều ngược lại: truyền thông tin từ thành phần con đến thành phần cha.
Mục đích của những việc chúng ta sẽ làm tiếp theo là kết thúc bằng trạng thái 'yêu thích' của một mặt hàng thực phẩm sẽ được thay đổi trong App.vue
gốc thay vì trong thành phần con FoodItem.vue
nơi sự thay đổi hiện đang diễn ra.
Lý do thay đổi trạng thái yêu thích trong App.vue
thay vì trong FoodItem.vue
là vì App.vue
là nơi lưu trữ trạng thái yêu thích ngay từ đầu nên cần phải cập nhật. Trong một dự án lớn hơn, dữ liệu có thể đến từ cơ sở dữ liệu mà chúng tôi kết nối trong App.vue
và chúng tôi muốn một thay đổi xảy ra từ thành phần này để tạo ra thay đổi trong cơ sở dữ liệu, vì vậy chúng tôi cần liên lạc lại với thành phần gốc từ thành phần con .
Phát ra một sự kiện tùy chỉnh
Cần phải gửi thông tin từ thành phần đến thành phần mẹ và chúng tôi sử dụng phương thức tích hợp sẵn $emit()
để thực hiện điều đó.
Chúng ta đã có phương thức toggleFavorite
bên trong thành phần FoodItem.vue
chạy khi nút chuyển đổi được nhấp vào. Bây giờ, hãy xóa dòng hiện có và thêm một dòng để phát ra sự kiện tùy chỉnh 'toggle-favorite' của chúng tôi:
FoodItem.vue
:
methods: {
toggleFavorite() {
this.foodIsFavorite = !this.foodIsFavorite;
this.$emit('toggle-Favorite');
}
}
Chúng ta có thể chọn tên cho sự kiện tùy chỉnh của mình, nhưng việc sử dụng kebab-case cho các sự kiện phát ra là điều bình thường.
Nhận một sự kiện phát ra
Sự kiện phát ra tùy chỉnh 'toggle-favorite' hiện được phát ra từ thành phần FoodItem.vue
, nhưng chúng ta cần lắng nghe sự kiện trong App.vue
cha và gọi một phương thức thực hiện điều gì đó để chúng ta có thể thấy sự kiện đó đã xảy ra.
Chúng ta lắng nghe sự kiện bằng cách viết tắt @
thay vì v-on:
trong App.vue
nơi thành phần được tạo:
Ví dụ
Nghe sự kiện 'toggle-favorite' trong App.vue
:
<food-item
v-for="x in foods"
:key="x.name"
:food-name="x.name"
:food-desc="x.desc"
:is-favorite="x.favorite"
@toggle-favorite="receiveEmit"
/>
Khi sự kiện tùy chỉnh 'toggle-favorite' xảy ra, chúng ta cần tạo phương thức receiveEmit
trong App.vue
để có thể thấy sự kiện đó đã xảy ra:
methods: {
receiveEmit() {
alert('Hello World!');
}
}
Chạy ví dụ »Thay đổi trạng thái 'yêu thích' của mặt hàng thực phẩm trong phần gốc
Bây giờ chúng tôi có một sự kiện thông báo cho App.vue
khi nút 'Yêu thích' được nhấp vào từ thành phần con.
Chúng tôi muốn thay đổi thuộc tính 'yêu thích' trong mảng 'thực phẩm' trong App.vue
cho đúng mặt hàng thực phẩm khi nhấp vào nút 'Yêu thích'. Để làm điều đó, chúng tôi gửi tên mặt hàng thực phẩm từ FoodItem.vue
đến App.vue
vì đó là tên duy nhất cho mỗi mặt hàng thực phẩm:
FoodItem.vue
:
methods: {
toggleFavorite() {
this.$emit('toggle-favorite' , this.foodName );
}
}
Bây giờ chúng ta có thể nhận tên mặt hàng thực phẩm trong App.vue
làm đối số cho phương thức được gọi khi sự kiện 'toggle-favorite' xảy ra, như sau:
Ví dụ
App.vue
:
methods: {
receiveEmit( foodId ) {
alert( 'You clicked: ' + foodId );
}
}
Chạy ví dụ »Bây giờ chúng ta đã biết mặt hàng thực phẩm nào được nhấp vào, chúng ta có thể cập nhật trạng thái 'yêu thích' cho mặt hàng thực phẩm chính xác bên trong mảng 'thực phẩm':
App.vue
:
methods: {
receiveEmit(foodId) {
const foundFood = this.foods.find(
food => food.name === foodId
);
foundFood.favorite = !foundFood.favorite;
}
}
Trong đoạn mã trên, phương thức mảng 'find' đi qua mảng 'foods' và tìm kiếm một đối tượng có thuộc tính name bằng với mặt hàng thực phẩm mà chúng ta đã nhấp vào và trả về đối tượng đó là 'foundFood'. Sau đó, chúng ta có thể đặt 'foundFood.health' đối lập với giá trị trước đó để nó chuyển đổi giữa true
và false
.
Tìm hiểu thêm về phương thức mảng JavaScript “find” tại đây .
Tìm hiểu thêm về các hàm mũi tên của JavaScript tại đây .
Thực phẩm chính xác bên trong mảng 'thực phẩm' hiện được cập nhật trạng thái 'yêu thích'. Việc duy nhất còn lại là cập nhật hình ảnh món ăn yêu thích.
Bởi vì các thành phần mặt hàng thực phẩm đã được tạo với trạng thái 'favorite' từ mảng 'foods' và được gửi dưới dạng prop 'is-favorite' từ App.vue
, nên chúng ta chỉ cần tham khảo prop 'isFavorite' này trong FoodItem.vue
từ v-show
trong đó phần tử <img>
dùng để cập nhật hình ảnh:
<img src="/img_quality.svg" v-show=" isFavorite ">
Chúng ta cũng có thể xóa thuộc tính dữ liệu 'foodIsFavorite' trong FoodItem.vue
vì nó không còn được sử dụng nữa.
Ví dụ
Trong mã ví dụ cuối cùng này, trạng thái yêu thích của các mặt hàng thực phẩm có thể được chuyển đổi theo cách tương tự như trước, nhưng bây giờ trạng thái yêu thích đã được sửa đổi ở đúng vị trí, bên trong App.vue
.
Tùy chọn 'phát ra'
Tương tự như cách chúng ta khai báo props bên trong thành phần FoodItem.vue
, chúng ta cũng có thể ghi lại những gì thành phần đó phát ra bằng cách sử dụng tùy chọn Vue 'emits'.
Đạo cụ phải được khai báo trong thành phần, trong khi các lần phát ra chỉ được khuyến nghị ghi lại.
Đây là cách chúng ta có thể ghi lại sự phát ra của mình trong thành phần FoodItem.vue
:
<script>
export default {
props: ['foodName','foodDesc','isFavorite'],
emits: ['toggle-favorite'],
methods: {
toggleFavorite() {
this.$emit('toggle-favorite', this.foodName);
}
}
};
</script>
Thành phần này trở nên dễ dàng hơn cho người khác sử dụng khi các lần phát ra được ghi lại.