前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >写一个 Vue 的插件 toast

写一个 Vue 的插件 toast

作者头像
EchoROne
发布2022-08-15 08:28:24
3260
发布2022-08-15 08:28:24
举报
文章被收录于专栏:玩转大前端

本人在造轮子过程中遇到写 toast 组件时为考虑方便用户调用,因此采用插件方式写 toast,

最终用户调用代码为

代码语言:javascript
复制
<template>
   <button @click="showToast"></button>
</template>

<script>
  export default {
    methods: {
     showToast() {
      this.$toast(`您的余额为 ${parseInt(Math.random() * 100)}. 需要充值`, {
        enableHtml: false, // 是否开启内嵌html元素
        autoClose: false, // 是否自动关闭
        position: 'top', // 展示位置
        closeButton: {  // 关闭按钮配置
          text: '充值',
          callback: (toast) => {
            toast.log() // 关闭后触发 toast 中的方法
          }
        }
      })
    }
  }
</script>

展示效果为

插件代码

代码语言:javascript
复制
import Toast from './toast.vue'

let currentToast
export default {
  install(Vue, options) {
    Vue.prototype.$toast = (message, toastOptions) => {
      // 避免出现多个 toast 重叠
      if(currentToast) {
        currentToast.close()
      }

      currentToast = createToast({
        Vue,
        message,
        propsData: toastOptions,
        onClose: () => {
          currentToast = null
        }
      })
    }
  }
}

function createToast({ Vue, message, propsData, onClose }) {
  const Constructor = Vue.extend(Toast)
  let toast = new Constructor({
    propsData
  })
  toast.$slots.default = [message]
  toast.$mount()
  toast.$on('close', onClose)
  document.body.appendChild(toast.$el)
  return toast
}

toast 组件代码

代码语言:javascript
复制
<template>
  <div class="wrapper" :class="toastClasses">
    <div class="toast" ref="toast">
      <div class="message">
        <slot v-if="!enableHtml"></slot>
        <div v-else v-html="$slots.default[0]"></div>
      </div>
      <div class="line" ref="line"></div>
      <span class="close" v-if="closeButton" @click="onClickClose">{{closeButton.text}}</span>
    </div>
  </div>
</template>
<script>
export default {
  name: "WheelToast",
  props: {
    autoClose: {
      type: [Boolean, Number],
      default: 5,
      validator(value) {
        return typeof value === 'boolean' || typeof value === 'number'
      }
    },
    closeButton: {
      type: Object,
      // 传 object 时得用函数返回,不然属性会被覆盖,跟 data 一个道理
      default() {
        return {
          text: "关闭",
          // 点击关闭按钮的回调函数
          callback: undefined
        }
      }
    },
    enableHtml: {
      type: Boolean,
      default: false
    },
    position: {
      type: String,
      default: "middle",
      validator(value) {
        return ["top", "middle", "bottom"].indexOf(value) >= 0;
      }
    }
  },
  computed: {
    toastClasses() {
      return [`position-${this.position}`];
    }
  },
  mounted() {
    this.updateStyle();
    this.execAutoClose();
  },
  methods: {
    updateStyle() {
      // 实现多行文字父元素需要用到 min-height,此时子元素 height 为 100% 获取不到父元素 height,因此异步获取父元素高
      this.$nextTick(() => {
        this.$refs.line.style.height = `${this.$refs.toast.getBoundingClientRect().height}px`;
      });
    },
    execAutoClose() {
      if (this.autoClose) {
        setTimeout(() => {
          this.close();
        }, this.autoClose * 1000);
      }
    },
    close() {
      this.$el.remove();
      this.$emit("close");
      this.$destroy();
    },
    log() {
      console.log("调用了 toast 的 log 方法");
    },
    onClickClose() {
      this.close();
      if (this.closeButton && typeof this.closeButton.callback === "function") {
        // 调用 callback 传入 this 可让调用回调时拿到 toast 实例,从而调用实例里的方法
        this.closeButton.callback(this);
      }
    }
  }
};
</script>

备注:为了简洁去掉了 css 代码

使用插件

代码语言:javascript
复制
import Vue from 'vue'
import plugin from './plugin'

Vue.use(plugin)

之后便可以在组件中用this.$toast(MESSAGE, OPTIONS)的方式调用 toast插件啦

总结

制作toast插件的详细过程可以查看我的造轮子项目https://github.com/zyqq/wheel/tree/toast toast分支下的commit记录

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-03-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 插件代码
  • toast 组件代码
  • 使用插件
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档