Như được đề cập bởi Chris Fritz (Vue.js Core Team Emeriti ) trong VueCONF US 2019
Nếu chúng ta có Kia nhập .native
và sau đó phần tử gốc của đầu vào cơ sở đã thay đổi từ đầu vào thành nhãn đột nhiên thành phần này bị hỏng và không rõ ràng và trên thực tế, bạn thậm chí có thể không nắm bắt được ngay lập tức trừ khi bạn có bài kiểm tra thực sự tốt. Thay vào đó, bằng cách tránh sử dụng công cụ .native
sửa đổi mà tôi hiện đang xem là một kiểu chống mẫu sẽ bị xóa trong Vue 3, bạn có thể xác định rõ ràng rằng phụ huynh có thể quan tâm đến trình lắng nghe phần tử nào được thêm vào ...
Với Vue 2
Sử dụng $listeners
:
Vì vậy, nếu bạn đang sử dụng Vue 2, một tùy chọn tốt hơn để giải quyết vấn đề này sẽ là sử dụng logic trình bao bọc hoàn toàn trong suốt . Đối với điều này, Vue cung cấp một thuộc $listeners
tính có chứa một đối tượng người nghe đang được sử dụng trên thành phần. Ví dụ:
{
focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },
}
và sau đó chúng ta chỉ cần thêm v-on="$listeners"
vào test
thành phần như:
Test.vue (thành phần con)
<template>
<div v-on="$listeners">
click here
</div>
</template>
Bây giờ <test>
thành phần này là một trình bao bọc hoàn toàn trong suốt , có nghĩa là nó có thể được sử dụng chính xác như một <div>
phần tử bình thường : tất cả các trình nghe sẽ hoạt động mà không cần .native
sửa đổi.
Bản giới thiệu:
Vue.component('test', {
template: `
<div class="child" v-on="$listeners">
Click here
</div>`
})
new Vue({
el: "#myApp",
data: {},
methods: {
testFunction: function(event) {
console.log('test clicked')
}
}
})
div.child{border:5px dotted orange; padding:20px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
<test @click="testFunction"></test>
</div>
Sử dụng $emit
phương pháp:
Chúng ta cũng có thể sử dụng $emit
phương pháp cho mục đích này, giúp chúng ta lắng nghe các sự kiện thành phần con trong thành phần cha mẹ. Đối với điều này, trước tiên chúng ta cần phải phát ra một sự kiện tùy chỉnh từ thành phần con như:
Test.vue (thành phần con)
<test @click="$emit('my-event')"></test>
Quan trọng: Luôn sử dụng kebab-case cho tên sự kiện. Để biết thêm thông tin và bản demo lấy lại điểm này, vui lòng kiểm tra câu trả lời này: VueJS chuyển giá trị được tính từ thành phần sang phần gốc .
Bây giờ, chúng ta chỉ cần lắng nghe sự kiện tùy chỉnh được phát ra này trong thành phần cha mẹ như:
Ứng dụng
<test @my-event="testFunction"></test>
Vì vậy, về cơ bản thay vì v-on:click
hoặc tốc ký, @click
chúng ta sẽ chỉ sử dụng v-on:my-event
hoặc chỉ @my-event
.
Bản giới thiệu:
Vue.component('test', {
template: `
<div class="child" @click="$emit('my-event')">
Click here
</div>`
})
new Vue({
el: "#myApp",
data: {},
methods: {
testFunction: function(event) {
console.log('test clicked')
}
}
})
div.child{border:5px dotted orange; padding:20px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
<test @my-event="testFunction"></test>
</div>
Với Vue 3
Sử dụng v-bind="$attrs"
:
Vue 3 sẽ làm cho cuộc sống của chúng ta dễ dàng hơn theo nhiều cách. Một trong những ví dụ cho nó là nó sẽ giúp chúng ta tạo ra một trình bao bọc trong suốt đơn giản hơn với cấu hình rất ít chỉ bằng cách sử dụng v-bind="$attrs"
. Bằng cách sử dụng điều này trên các thành phần con, không chỉ người nghe của chúng ta sẽ làm việc trực tiếp từ cha mẹ mà còn bất kỳ thuộc tính nào khác cũng sẽ hoạt động giống như nó một cách bình thường <div>
.
Vì vậy, đối với câu hỏi này, chúng tôi sẽ không cần cập nhật bất cứ điều gì trong Vue 3 và mã của bạn sẽ vẫn hoạt động tốt như <div>
là phần tử gốc ở đây và nó sẽ tự động lắng nghe tất cả các sự kiện con.
Bản thử nghiệm số 1:
const { createApp } = Vue;
const Test = {
template: `
<div class="child">
Click here
</div>`
};
const App = {
components: { Test },
setup() {
const testFunction = event => {
console.log("test clicked");
};
return { testFunction };
}
};
createApp(App).mount("#myApp");
div.child{border:5px dotted orange; padding:20px;}
<script src="//unpkg.com/vue@next"></script>
<div id="myApp">
<test v-on:click="testFunction"></test>
</div>
Nhưng đối với các thành phần phức tạp với các thành phần lồng nhau, trong đó chúng ta cần áp dụng các thuộc tính và sự kiện cho chính <input />
thay vì nhãn chính, chúng ta có thể chỉ cần sử dụngv-bind="$attrs"
Bản thử nghiệm số 2:
const { createApp } = Vue;
const BaseInput = {
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input v-bind="$attrs">
</label>`
};
const App = {
components: { BaseInput },
setup() {
const search = event => {
console.clear();
console.log("Searching...", event.target.value);
};
return { search };
}
};
createApp(App).mount("#myApp");
input{padding:8px;}
<script src="//unpkg.com/vue@next"></script>
<div id="myApp">
<base-input
label="Search: "
placeholder="Search"
@keyup="search">
</base-input><br/>
</div>
@click.native="testFunction"