Vue Snackbar message bar queue display, in order to achieve the disappearance of animation

Vue Snackbar message bar queue display, in order to achieve the disappearance of animation

Results preview

Thinking

  1. Snackbar assembly package;
  2. Snackbar establish global controller in the root page routing, unified management Snackbar;
  3. Snackbar global event notification controller displays a message;

achieve

1. Packaging assembly Snackbar

project/src/components/snackbar.vue

<template>
  <div class="component-snackbar" v-if="value">
    <div class="snackbar-content">{{ message }}</div>
    <div class="snackbar-close" v-if="closable" @click="close">关闭</div>
  </div>
</template>

<script>
export default {
  name: "component-snackbar",
  props: {
    value: Boolean, // 调用本组件v-model传入的值
    message: String, // 消息内容
    closable: { // 是否显示删除按钮
      type: Boolean,
      default: false
    }
  },
  data: function() {
    return {
      showTime: 6000, // snackbar显示的时长
      timer: null // 定时器
    }
  },
  mounted() {
    // 在 showTime 到期后自动关闭snackbar
    this.timer = setTimeout(() => {
      this.close()
    }, this.showTime)
  },
  methods: {
    close() {
      // 清除定时器
      clearTimeout(this.timer)
      // 不能直接在组件中修改props中的数据,因此不能直接修改this.value = false
      // 而是实现了在自定义组件中使用v-model,通过外传 input 事件通知调用者自动更新 v-model 传入的值
      this.$emit('input', false)
    }
  }
}
</script>

<style lang="less">
.component-snackbar {
  width: 400px;
  height: 60px;
  position: fixed;
  right: 10px;
  bottom: 10px;
  display: flex;
  flex-direction: row;
  align-items: center;
  border-radius: 8px;
  background-color: #333333;
  box-shadow: 2px 4px 6px 0 rgba(0,0,0,.4);
  transition: transform 500ms ease-in;
  .snackbar-content {
    flex: 1;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    padding: 0 16px;
  }
  .snackbar-close {
    margin: 0 16px;
    color: deeppink;
    cursor: pointer;
  }
}
</style>

2. Global Snackbar controller

  • Sign up event bus EventBus;

    project/src/main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

// 创建 Vue 的实例作为事件总线使用,将其挂载到 $eventBus 上,
// 即可在组件中直接使用 this.$eventBus.$emit() 和 this.$eventBus.$on() 来触发/监听事件
Vue.prototype.$eventBus = new Vue()

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')
  • Global Snackbar controller
    global controller listens Snackbar at the root page showSnackbar routing events, and maintain a list of messages, by listening to events pushed ordered to delete the messages, so as to achieve the purpose of controlling Snackbar display;

    project/src/App.vue

<template>
  <div id="app">
    <router-view />

    <!-- 全局 Snackbar 队列 -->
    <!-- 根据当前 Snackbar 的 index 动态计算 Y 方向的位移,达到依次排列的目的 -->
    <snackbar
      v-model="item.show"
      :style="{transform: 'translateY(' + -(60+10) * index + 'px)'}"
      :message="item.content"
      :closable="item.closable"
      v-for="(item, index) in messages"
      :key="item.id"
      @input="onSnackbarClose($event, index)"></snackbar>
  </div>
</template>

<script>
import Snackbar from './components/snackbar'

export default {
  name: "app",
  components: {
    Snackbar
  },
  data: function() {
    return {
      messages: [] // 消息队列
    }
  },
  mounted() {
    // 全局 Snackbar 控制器事件监听
    this.snackbarController()
  },
  methods: {
    snackbarController() {
      // 监听 showSnackbar 事件
      this.$eventBus.$on('showSnackbar', data => {
        // 将收到的message推入messages数组中
        this.messages.push({
          ...data,
          show: true
        })
      })
    },
    onSnackbarClose(value, index) {
      // value 为 Snackbar 组件内部传递出来的
      // index 为当前关闭 Snackbar 的 索引
      // 删除已关闭的 Snackbar 对应的消息数据
      this.messages.splice(index, 1)
    }
  }
}
</script>

<style lang="less">
* {
  box-sizing: border-box;
}
body {
  margin: 0;
  padding: 0;
  background-color: #212121;
  color: #cecece;
  font-size: 14px;
}
</style>

3. Call Snackbar

This page is an analog trigger message;

project / src / views / snackbar.vue

<template>
  <div class="view-snackbar">
    <div class="wrap">
      <input type="text" v-model="msg" class="msg-input" placeholder="说点什么...">
      <div class="btn" @click="showMessage">显示消息</div>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'view-snackbar',
    data: function () {
      return {
        msg: ''
      }
    },
    methods: {
      showMessage() {
        // 通过触发 showSnackbar 事件并传递消息参数,从而调用全局 Snackbar
        this.$eventBus.$emit('showSnackbar', {
          id: new Date().getTime(), // id 用于设置 Snackbar 在 v-for 循环中的 key 属性,避免排序混乱的问题
          content: this.msg,
          closable: true
        })
      }
    }
  }
</script>

<style lang="less">
.view-snackbar {
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-image: url(https://img.cc0.cn/pixabay/2019102201563350617.jpg/content);
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
  .wrap {
    width: 240px;
  }
  .msg-input {
    width: 100%;
    height: 40px;
    color: inherit;
    background-color: #333333;
    border: 2px solid #444444;
    border-radius: 8px;
    outline: none;
    padding: 0 8px;
  }
  .btn {
    width: 120px;
    margin: 20px auto;
    padding: 8px 0;
    text-align: center;
    border-radius: 8px;
    background-color: deeppink;
    cursor: pointer;
    user-select: none;
  }
}
</style>

4. Summary

Through the above steps 4 to achieve a simple Vue Snackbar queue message bar displayed animation sequence and disappears, the idea is very clear, there are three main points:

  • Use the global controller, and pass messages through event bus $ eventBus;
  • Using v-model implemented in custom components of Snackbar deleted;
  • Dynamically calculating the displacement in the Y direction by orderly aligned Snackbar Snackbar index;

This tutorial is intended to describe the idea is relatively simple, without making excessive packaging and customizing, hoping to help needy children's shoes, if found any problems or more implementations, welcome to discuss!

5. Improve

Can do more to improve in this edition, based on the interest of their own children's shoes can play;

  • Snackbar gradual appearance / disappearance;
  • Snackbar mixture of various heights;

Guess you like

Origin www.cnblogs.com/zhenfengxun/p/12452814.html