Vue.js 中的组件未捕获自定义事件
Custom event not captured by component in Vue.js
这是我的组件架构
组件 <ListButtonMenu>
发出自定义事件 display-error
,如下所示。发射工作正常,因为我可以在 VueDevtools 中看到该事件:
<template>
<div>
<button type="button" class="btn btn-success" v-on:click="saveList()">
Save
</button>
</div>
</template>
<script>
export default {
props: {
list: Object
},
methods: {
saveList() {
this.$emit('display-error');
}
}
}
</script>
组件 <ErrorMessage>
包含一个 div
元素,它侦听自定义事件并调用方法 display()
。该方法更改组件 CSS class 以显示自己:v-on:display-error="display"
。不幸的是,这不起作用并且 CSS class 没有改变。我错过了什么?
<template>
<div id="errorMessage" v-bind:class="cssClass" v-on:display-error="display()">
<div class="row justify-content-center alert alert-danger alert-dismissable text-danger">
Error: {{ errorMessage }}
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">
×
</button>
</div>
</div>
</template>
<script>
export default {
data: function () {
return {
'cssClass': 'd-none',
'errorMessage': 'Hello'
}
},
methods: {
display() {
this.cssClass = 'show';
this.errorMessage='Goodbye';
}
}
}
</script>
错误侦听器必须附加到发出事件的元素。当你有 <div id="errorMessage" v-bind:class="cssClass" v-on:display-error="display()">
时,这会为 div 发出事件添加一个侦听器,但事件不是来自 div,它来自你的 ListButtonMenu
。您需要向该元素添加 v-on
指令,如下所示:
<ListButtonMenu v-on="display()" other="attributes"></ListButtonMenu>
编辑:
您的 ErrorMessage 元素需要像这样接受来自 parent 的错误(请注意为关闭按钮添加的 $emit
):
<template>
<div id="errorMessage" v-bind:class="cssClass" v-on:display-error="display()">
<div class="row justify-content-center alert alert-danger alert-dismissable text-danger">
Error: {{ errorMessage }}
<button v-on:click="$emit('input', false)" type="button" class="close" data-dismiss="alert" aria-hidden="true">
×
</button>
</div>
</div>
</template>
<script>
export default {
props: [
'errorMessage',
'value', // Generally value is used to toggle things so that v-model works
],
computed: {
cssClass() {
return this.value ? 'show' : 'd-none';
}
}
methods: {
display() {
this.cssClass = 'show';
this.errorMessage='Goodbye';
}
}
}
</script>
然后你的 parent 看起来像这样:
<template>
<error-message v-model="showError" v-bind:errorMessage="errorMessage">
<list-button-menu v-on:display-error="displayError()"></list-button-menu>
</template>
<script>
export default {
data: function() {
return {
errorMessage: 'Hello',
showError: false,
}
},
methods: {
displayError() {
this.showError = true;
this.errorMessage: 'Goodbye';
}
}
}
</script>
因为我的 ErrorMessage
和 ListButtonMenu
组件没有父子关系,所以我选择了与使用自定义事件不同的解决方案。
相反,我使用我的应用程序状态(使用 Vuex 存储构建)作为事件总线来更新 errorObject
并且 ErrorMessage
组件使用计算属性来捕获 errorObject
并展示自己。
我的组件架构与问题中的相同。
这是文件 store.js:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
errorObject: {
flag: false,
message: ''
}
}
});
这是 ListButtonMenu 组件:
<template>
<div>
<button type="button" class="btn btn-success" v-on:click="saveList()">
Save
</button>
</div>
</template>
<script>
export default {
props: {
list: Object
},
methods: {
saveList() {
this.$store.state.errorObject.flag = true;
this.$store.state.errorObject.message = 'My error mesage';
}
}
}
</script>
这里是 ErrorMessage 组件;
<template>
<div id="errorMessage" v-bind:class="cssClass">
<div class="row justify-content-center alert alert-danger alert-dismissable text-danger">
Error: {{ errorMessage }}
<button type="button" class="close" v-on:click="close()">
×
</button>
</div>
</div>
</template>
<script>
export default {
data: function () {
return {
}
},
computed: {
cssClass() {
if (this.$store.state.errorObject.flag) { return 'display' }
else { return 'd-none' }
},
errorMessage() {
return this.$store.state.errorObject.message;
}
},
methods: {
close() {
this.$store.state.errorObject.flag = false;
this.$store.state.errorObject.message= '';
}
}
}
</script>
这是我的组件架构
组件 <ListButtonMenu>
发出自定义事件 display-error
,如下所示。发射工作正常,因为我可以在 VueDevtools 中看到该事件:
<template>
<div>
<button type="button" class="btn btn-success" v-on:click="saveList()">
Save
</button>
</div>
</template>
<script>
export default {
props: {
list: Object
},
methods: {
saveList() {
this.$emit('display-error');
}
}
}
</script>
组件 <ErrorMessage>
包含一个 div
元素,它侦听自定义事件并调用方法 display()
。该方法更改组件 CSS class 以显示自己:v-on:display-error="display"
。不幸的是,这不起作用并且 CSS class 没有改变。我错过了什么?
<template>
<div id="errorMessage" v-bind:class="cssClass" v-on:display-error="display()">
<div class="row justify-content-center alert alert-danger alert-dismissable text-danger">
Error: {{ errorMessage }}
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">
×
</button>
</div>
</div>
</template>
<script>
export default {
data: function () {
return {
'cssClass': 'd-none',
'errorMessage': 'Hello'
}
},
methods: {
display() {
this.cssClass = 'show';
this.errorMessage='Goodbye';
}
}
}
</script>
错误侦听器必须附加到发出事件的元素。当你有 <div id="errorMessage" v-bind:class="cssClass" v-on:display-error="display()">
时,这会为 div 发出事件添加一个侦听器,但事件不是来自 div,它来自你的 ListButtonMenu
。您需要向该元素添加 v-on
指令,如下所示:
<ListButtonMenu v-on="display()" other="attributes"></ListButtonMenu>
编辑:
您的 ErrorMessage 元素需要像这样接受来自 parent 的错误(请注意为关闭按钮添加的 $emit
):
<template>
<div id="errorMessage" v-bind:class="cssClass" v-on:display-error="display()">
<div class="row justify-content-center alert alert-danger alert-dismissable text-danger">
Error: {{ errorMessage }}
<button v-on:click="$emit('input', false)" type="button" class="close" data-dismiss="alert" aria-hidden="true">
×
</button>
</div>
</div>
</template>
<script>
export default {
props: [
'errorMessage',
'value', // Generally value is used to toggle things so that v-model works
],
computed: {
cssClass() {
return this.value ? 'show' : 'd-none';
}
}
methods: {
display() {
this.cssClass = 'show';
this.errorMessage='Goodbye';
}
}
}
</script>
然后你的 parent 看起来像这样:
<template>
<error-message v-model="showError" v-bind:errorMessage="errorMessage">
<list-button-menu v-on:display-error="displayError()"></list-button-menu>
</template>
<script>
export default {
data: function() {
return {
errorMessage: 'Hello',
showError: false,
}
},
methods: {
displayError() {
this.showError = true;
this.errorMessage: 'Goodbye';
}
}
}
</script>
因为我的 ErrorMessage
和 ListButtonMenu
组件没有父子关系,所以我选择了与使用自定义事件不同的解决方案。
相反,我使用我的应用程序状态(使用 Vuex 存储构建)作为事件总线来更新 errorObject
并且 ErrorMessage
组件使用计算属性来捕获 errorObject
并展示自己。
我的组件架构与问题中的相同。 这是文件 store.js:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
errorObject: {
flag: false,
message: ''
}
}
});
这是 ListButtonMenu 组件:
<template>
<div>
<button type="button" class="btn btn-success" v-on:click="saveList()">
Save
</button>
</div>
</template>
<script>
export default {
props: {
list: Object
},
methods: {
saveList() {
this.$store.state.errorObject.flag = true;
this.$store.state.errorObject.message = 'My error mesage';
}
}
}
</script>
这里是 ErrorMessage 组件;
<template>
<div id="errorMessage" v-bind:class="cssClass">
<div class="row justify-content-center alert alert-danger alert-dismissable text-danger">
Error: {{ errorMessage }}
<button type="button" class="close" v-on:click="close()">
×
</button>
</div>
</div>
</template>
<script>
export default {
data: function () {
return {
}
},
computed: {
cssClass() {
if (this.$store.state.errorObject.flag) { return 'display' }
else { return 'd-none' }
},
errorMessage() {
return this.$store.state.errorObject.message;
}
},
methods: {
close() {
this.$store.state.errorObject.flag = false;
this.$store.state.errorObject.message= '';
}
}
}
</script>