Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

做一个Vue的Toast组件 #163

Open
louzhedong opened this issue Jun 28, 2019 · 0 comments
Open

做一个Vue的Toast组件 #163

louzhedong opened this issue Jun 28, 2019 · 0 comments

Comments

@louzhedong
Copy link
Owner

本文来基于Vue实现一个Toast组件

要点

基于Vue.extend()方法,我们可以得到一个Vue组件的实例,并且操作这个实例

Toast.js

import Vue from 'vue';
import ToastCompent from './Toast.vue';

const instancePool = []; // 实例池
const ToastConstructor = Vue.extend(ToastCompent);

const getAnInstance = () => {
  if (instancePool.length > 0) {
    const instance = instancePool.shift();
    return instance;
  }
  return new ToastConstructor({
    el: document.createElement('div')
  });
}

const removeDom = (event) => {
  if (event.target.parentNode) {
    event.target.parentNode.removeChild(event.target);
  }
}

ToastConstructor.prototype.close = function () {
  this.visible = false;
  this.$el.addEventListener('transitionend', removeDom);
  this.closed = true;
  // 关闭后将实例存入实例池
  instancePool.push(this);
}

/**
 *
 *
 * @param {*} [options={
 * message
 * backgroundColor: rgba(0, 0, 0, 0.7)
 * position ['top', 'middle', 'bottom']
 * duration 3000 -1为不关闭
 * className
 * }]
 * options 也可以是一个字符串
 */
const Toast = (options = {}) => {
  const duration = options.duration || 3000;
  let instance = getAnInstance();
  instance.closed = false;
  clearTimeout(instance.timer);

  instance.message = typeof options === 'string' ? options : options.message;
  instance.backgroundColor = options.backgroundColor || 'rgba(0, 0, 0, 0.7)';
  instance.position = options.position || 'top';
  instance.duration = options.duration || 3000;
  instance.className = options.className || '';

  document.body.appendChild(instance.$el);

  Vue.nextTick(() => {
    instance.visible = true;
    instance.$el.removeEventListener('transitionend', removeDom);
    ~duration && (instance.timer = setTimeout(() => {
      if (instance.closed) return;
      instance.close();
    }, duration))
  });

  return instance;
}

export default Toast;

Toast.vue

<template>
  <transition name="fade">
    <div
      class="wheat-toast"
      :class="computedClass"
      :style="{'background': backgroundColor}"
      v-show="visible"
    >
      <span class="wheat-toast-message">{{message}}</span>
    </div>
  </transition>
</template>

<script type="text/babel">
export default {
  props: ["message", "backgroundColor", "position", "duration", "className"],

  data() {
    return {
      visible: false
    };
  },

  computed: {
    computedClass() {
      let classname = this.className;
      switch (this.position) {
        case "top":
          classname += " toast-position-top";
          break;
        case "middle":
          classname += " toast-position-middle";
          break;
        case "bottom":
          classname += " toast-position-bottom";
          break;
        default:
          break;
      }
      return classname;
    }
  }
};
</script>

<style lang="less">
.wheat-toast {
  position: fixed;
  max-width: 80%;
  border-radius: 5px;
  color: #fff;
  box-sizing: border-box;
  text-align: center;
  z-index: 1000;
  padding: 8px 12px;
  font-size: 16px;
  .wheat-toast-message {
    font-size: inherit;
  }
}
.toast-position-top {
  top: 50px;
  left: 50%;
  transform: translate(-50%, 0);
}

.toast-position-middle {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.toast-position-bottom {
  bottom: 50px;
  left: 50%;
  transform: translate(-50%, 0);
}

.fade-enter,
.fade-leave-to {
  opacity: 0;
}

.fade-enter-to,
.fade-leave {
  opacity: 1;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s;
}
</style>

使用方式

<template>
  <div class="toast-example">
    <div class="beautify-button" @click="handleShowToast">显示弹窗</div>
  </div>
</template>

<script>
import Toast from "wheat-ui/dist/Toast";
export default {
  methods: {
    handleShowToast() {
      Toast({
        message: "出现错误",
        position: "middle"
      });

      Toast("只有message");


      const instance = Toast({
        message: "不关闭",
        duration: -1
      });
      setTimeout(() => {
        instance.close();
      }, 4000);
    }
  }
};
</script>
​```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant