vue封装一个类似于element-ui的Notice通知组件,并挂载到Vue原型上使用this.$Notice.xxx()调用

功能介绍:点击对应的按钮会在浏览器最右边向左边滑动展示,点击隐藏按钮会滑动向右隐藏,或者设置时间多久关闭,点击不同的按钮会展示不同的icon图标,如果只需要title而不需要内容只需要传递一个布尔值即可实现;效果如下:

默认效果: 

 只展示title:

展示成功按钮以及内容: 

1、在components中新建一个Notice.vue文件,作为Notice组件,创建好随便写点啥

2、新建一个Notice.js,在里面编写Vue方式实例,并在Vue原型上挂载一个$Notice方法

Notice.js代码如下:

import Notice from './Notice.vue'
let NoticeInstance = null
const NoticePlugin = {
  install(Vue) {
    if(!NoticeInstance) {
      const NoticeComponent = Vue.extend(Notice)
      NoticeInstance = new NoticeComponent()
      const container = document.createElement('div')
      document.body.appendChild(container)
      NoticeInstance.$mount(container)
    }
  }
}
export default NoticePlugin

3、在main.js中引入:

import NoticePlugin from './components/Notice/Notice'
Vue.use(NoticePlugin)

此时在页面中就已经可以展示组件了 

4、接下来我们在Notice.js原型上添加两个方法open打开,close关闭;以及成功,失败...的方法代码如下:

Vue.prototype.$notice = {
      // 接受四个个参数 top, title, desc, duration // 不传就是默认值
      open: ({top = 30, title, desc, duration = 3000}) => {
        NoticeInstance.open({top, title, desc, duration})
      },
      // type 图标类型
      warning: ({top = 30, title, desc, duration = 3000}) => {
        NoticeInstance.iconType({top, title, type: 'warning', desc, duration})
      },
      success: ({top = 30, title, desc, duration = 3000}) => {
        NoticeInstance.iconType({top, title, type: 'success', desc, duration})
      },
      error: ({top = 30, title, desc, duration = 3000}) => {
        NoticeInstance.iconType({top, title, type: 'error', desc, duration})
      },
      info: ({top = 30, title, desc, duration = 3000}) => {
        NoticeInstance.iconType({top, title, type: 'info', desc, duration})
      },
      close: () => {
        NoticeInstance.close()
      }
    }

在原型中我们添加了六个个方法,默认接收4个参数, 其中带图标的方法返回五个参数:type是判断图标类型的唯一标识 top:距离顶部的距离,title: 标题,desc:内容, duration:展示的时间 ;其中top,duration不传的话给默认值;这两个方法会自动调用Notice.vue的open和close方法:注意:第一个open是挂载在原型的方法;我们需要用this.$Notice.open()调用原型上的方法,第二个是组件中open的方法,其它的方法同理;

5、美化Notice.vue的代码样式:

<template>
  <div class="notice" ref="notice" :style="{ top: top + 'px'}">
    <div class="lx-notice" style="display: flex;">
      <div class="lx-notice-icon-left" v-if="iconColor">
        <i class="iconfont" :class="iconColor"></i>
      </div>
      <div class="lx-notice-container">
        <div class="lx-notice-title">{{ title }}</div>
        <div class="lx-notice-desc">{{ desc }}</div>
      </div>
      <i class="iconfont icon-guanbi-close lx-notice-icon" @click="close"></i>
    </div>
  </div>
</template>

<script>
export default {
  // eslint-disable-next-line vue/multi-word-component-names
  name: 'Notice',
  data() {
    return {
      title: '',
      desc: '',
      duration: null,
      top: null,
      time: null,
      type: '',
    }
  },
  computed: {
    iconColor() {
      if(this.type === 'warning') {
        return `lx-notice-icon-warning icon-jinggao-fill`
      } else if(this.type === 'success') {
        return `lx-notice-icon-success icon-a-icon_wancheng-complete-fill1`
      } else if(this.type === 'error') {
        return `lx-notice-icon-error icon-guanbi-close`
      } else if(this.type === 'info') {
        return `lx-notice-icon-info icon-xinxi-info-fill`
      }
      return false
    }
  },
  methods: {
    base(obj) {
      this.top = obj.top
      this.type = obj.type
      this.title = obj.title
      this.desc = obj.desc
      this.duration = obj.duration
      this.$refs.notice.style.transform = 'translateX(-420px)'
      if(this.time) {
        this.time = clearTimeout(this.time)
      }
      this.time = setTimeout(() => {
        this.close()
      }, this.duration);
    },
    open(obj) {
      this.base(obj)
    },
    iconType(obj) {
      this.base(obj)
    },
    close() {
      if(this.time) {
        this.time = clearTimeout(this.time)
      }
      this.$refs.notice.style.transform = 'translateX(0)'
    }
  }
}
</script>
<style>
@import url('../../assets/icon/iconfont.css');
</style>
<style scoped lang="less">
.notice {
  width: 350px;
  background-color: #fff;
  box-shadow: 2px 2px 16px hsla(0, 0%, 72%, 0.5);
  position: fixed;
  right: -400px;
  padding: 15px;
  font-family: '微软雅黑';
  transition: all 0.6s;
  box-sizing: border-box;
}
.lx-notice-title {
  margin-bottom: 15px;
  font-weight: 600;
  font-size: 18px;
}
.lx-notice-icon-left {
  margin-right: 15px;
}
// 警告
.lx-notice-icon-warning {
  color: #ff9900;
}
.icon-jinggao-fill, .icon-a-icon_wancheng-complete-fill1, .icon-guanbi-close, .lx-notice-icon-info {
  font-size: 22px;
}
// 成功
.lx-notice-icon-success {
  color: #19be6b;
}
// 失败
.lx-notice-icon-error {
  color: #ee3c10;
}
// 信息
.icon-xinxi-info-fill {
  color: #2d8cf0;
}
.lx-notice-icon {
  position: absolute;
  top: 10px;
  right: 10px;
  cursor: pointer;
}
.lx-notice-hidden {
  display: none;
}
</style>

在上述代码中,添加了一个计算属性,根据传递过来的 type 属性判断添加相应的 icon 类名;当返回为 false的时候,说明传递的是默认,不需要添加类名 只使用 v-if 隐藏icon图标的盒子 

6、测试代码

当我们传递了一个ture说明是只需要title,不需要内容 

  

默认展示的notice 框 

调用了success方法:展示图标以及内容 :剩下的方法同理

  • 38
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值