VueJS显示和隐藏消息

时间:2018-01-27 22:49:30

标签: javascript vue.js settimeout

我创建了一个基本的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秒钟?这将是我首选的方法,否则我该怎么做才能让点击和隐藏工作?

非常感谢!

4 个答案:

答案 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)
  }