我创建了一个基本的CLI结构环境。我有一个组件来显示消息/警报即:登录失败等...
由于这个组件将在整个应用程序中重用,我想将它导入到根App.vue文件并在那里处理。它正在......有点......
它显示消息/警报很好,但我希望它在一定的秒数后隐藏/消失/蒸发。或者单击一个按钮,它会隐藏/消失/蒸发 - 我在下面的警报组件示例中显示了这一点。在一定的预定时间之后我无法获得隐藏,并且点击和隐藏起作用,但是不隐藏也会产生问题。我在App.vue文件中使用了setTimeout方法在5秒后自动隐藏,并且没有任何反应我认为该方法在导入Alert模块之前触发...我认为。
到目前为止,这是我的代码......似乎这么简单的任务,但过去几个小时它一直在破坏我的大脑:
应用组件:
<template>
<div id="app">
<alert v-if="alert" v-bind:message="alert"></alert>
<router-view></router-view>
</div>
</template>
<script>
import Alert from './components/frontend/alert'
export default {
name: 'App',
data() {
return {
alert: ''
}
},
updated: function() {
if(this.$route.query.alert){
this.alert = this.$route.query.alert;
// This was for me to test the click even - PREFER AUTO HIDE AFTER A FEW SECONDS
// This returns an error on form submit - see error below
document.querySelector('.alert').style.display = 'block';
}
},
components: {
'alert': Alert
}
}
</script>
以下是警报组件:
<template>
<div class="alert">
<p class="text-brand m-20">
<button class="btn btn-small btn-brand" v-on:click="hideAlert()">Close</button>
{{message}}
</p>
</div>
</template>
<script>
export default {
name: 'alert',
props: ['message'],
data () {
return {
}
},
methods: {
hideAlert() {
// This was for me to test the click even - PREFER AUTO HIDE AFTER A FEW SECONDS
document.querySelector('.alert').style.display = 'none';
}
}
}
</script>
使用点击隐藏时出错 - 来自App.vue文件:
[Vue warn]: Error in updated hook: "TypeError: Cannot read property 'style' of null"
found in
---> <App> at src/App.vue
<Root>
如何在应用程序根组件之后隐藏警报组件,比如5秒钟?这将是我首选的方法,否则我该怎么做才能让点击和隐藏工作?
非常感谢!
答案 0 :(得分:6)
document.querySelector('.alert').style.display = 'none';
不要这样做。你不应该在方法中操作DOM,只能在指令和生命周期钩子等规定的位置操作。在他们之外,Vue希望控制DOM。
您可以使用viewmodel控制inline styles。你也可以conditional rendering with v-if
。 Vue方法是您操纵模型并让Vue让DOM反映它。
我已将您的代码调整为下面的可运行代码段。
由于您将hideAlert方法放在组件中,因此我将关联的v-if
放在那里。测试是message
(道具)是否具有值,因此关闭是让父母清除消息的问题。这是使用the .sync
modifier处理的标准通信功能。
关闭按钮调用hideAlert
方法,我还放入一个观察者,以便每当设置新消息时,它等待5秒并调用hideAlert
。
警报组件是独立的;无论父级是否从路由器组件获取它,它的支柱如何获得其值并不重要,例如,它是否具有值是否重要。
const Alert = {
template: '#alert-template',
props: ['message'],
methods: {
hideAlert() {
// Tell the parent to clear the message
this.$emit('update:message', '');
}
},
watch: {
message(newValue) {
// Close after 5 seconds
if (newValue) {
setTimeout(this.hideAlert, 5000);
}
}
}
};
new Vue({
el: '#app',
data() {
return {
alert: ''
}
},
components: {
'alert': Alert
},
mounted() {
// If alert has a value, it will display. If not, not.
setTimeout(() => {
this.alert = 'Now you have a message';
}, 500);
}
});
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
<alert v-bind:message.sync="alert"></alert>
</div>
<template id="alert-template">
<div v-if="message" class="alert">
<p class="text-brand m-20">
<button class="btn btn-small btn-brand" v-on:click="hideAlert()">Close</button>
{{message}}
</p>
</div>
</template>
答案 1 :(得分:1)
首先,了解Vue和v-if
指令非常重要。 v-if
评估它的表达式,如果它的计算结果为true
,那么Vue将在DOM中呈现该元素,但如果没有,则该元素将不包含在DOM中。
这会导致您看到的错误消息,因为当没有要显示的警告时,DOM中没有符合document.querySelector('.alert')
的元素。
此外,如果您在一个组件中隐藏/显示所有代码,那会更好。例如,如果您希望它在父组件中,则hideAlert()
方法应为:
methods: {
hideAlert() {
this.alert = null
}
}
您的提醒按钮组件将是:
<button class="btn btn-small btn-brand" v-on:click="$emit('hide')">Close</button>
如果您在父级中拥有<alert>
标记,则会变为:
<alert v-if="alert" v-bind:message="alert" @hide="hideAlert"></alert>
答案 2 :(得分:0)
很抱歉碰到这个线程,但是我认为这是实现这一目标的最佳方法:
示例:假设我们有以下来自服务器响应的数据
data() {
return {
serverMessages: [],
}
},
methods: {
onSubmit() {
this.$axios.$get('/myroute')
.then(res => {
this.serverMessages.push(res)
this.$emit('flush-message')
})
.catch(err => {
this.serverMessages.push(err.data)
this.$emit('flush-message')
});
},
mounted() {
let timer
this.$on('flush-message', message => {
clearTimeout(timer)
timer = setTimeout(() => {
this.serverMessages = []
}, 3000)
})
}
这样,您可以清除超时,例如,如果有多个消息,则不会出现小故障。您还可以将类似的代码集成到单独的控制器中。
答案 3 :(得分:0)
您应该使用创建的生命周期将其隐藏在警报组件中,以将其隐藏,如下所示:
`
created: {
setTimeout(() => this.message = [], 1000)
}