今天教大家使用vue2封装一个全局可用的message提示组件

本文详细介绍了如何在Vue应用中实现一个可配置的全局Message组件,包括组件创建、字体图标引入、安装方法、通知方法的添加,以及使用$MessageAPI触发通知的示例。
摘要由CSDN通过智能技术生成

像element-ui,ViewDesgin这种组件库我们肯定使用过,当我们用message组件的时候可以直接this.$Message.loadong/success/error,... 那么这个是怎么实现的呢,今天教大家实现一个message组件挂载到vue全局

1、创建一个Message组件,在components目录下新建一个MessageComponent.vue;随便写点什么上去先

 2、在iconfont.cn中找自己需要的图标

下载下来后解压,在assets目录下新建icon文件夹 ,将以下的代码复制到icon文件中:

 记得改一下引入的地址:

在MessageComponent中引入字体图标:

<style scoped>
@import url('../assets/icon/iconfont.css');
</style>

好了,至此字体图标已经完成了。

3、核心逻辑 :

编写 omponents文件夹下的 MessageComponent.js 入口文件,首先定义一个全局变量避免组件多次创建,然后实现 install 方法,因为 Vue.use() 会调用 install ,那自然我们就可以在 intsall 方法参数里获取到 Vue实例了。

我们通过 Vue.extend 创建一个组件构造器,传入之前编写好的组件 MessageComponent.vue ,这样组件构造器就定义好了,使用 new 关键字对组件进行实例化得到一个组件实例 MessageInstanse。

然后将组件实例挂载到DOM,至此插件的核心逻辑就完成了。

import Message from './MessageComponent.vue'
let MessageInstanse = null
const MessagePlugin = {
  install(Vue) {
    if (!MessageInstanse) {
      // Vue.extend() 方法创建了一个名为 MessageComponent 的组件构造器。
      const MessageComponent = Vue.extend(Message);
      MessageInstanse = new MessageComponent();
      // 将通知组件挂载到DOM中
      const container = document.createElement("div");
      document.body.appendChild(container);
      MessageInstanse.$mount(container);
    }
}
export default MessagePlugin

4、下面我们在 main.js 中引入插件并使用。


// 全局的插件
import MessagePlugin from './components/MessageComponent'
Vue.use(MessagePlugin)

 启动项目并在浏览器打开,可以看到组件成功挂在到DOM。

5、实现通知方法:

想通过 this.$notify.success() 这样的方式调用,上面可以拿到Vue实例了,给实例原型添加属性;在MessageComponent.js中:添加了四个方法

Vue.prototype.$Message = {
      // 加载
      loading: (message, duration = 1000 * 60 * 60 * 24) => {
        MessageInstanse.showMessage(message, 'loading', duration)
      },
      // 成功
      success: (message, duration) => {
        MessageInstanse.showMessage(message, 'success', duration)
      },
      // 失败
      error: (message, duration) => {
        MessageInstanse.showMessage(message, 'error', duration)
      },
      // 警告
      warning: (message, duration) => {
        MessageInstanse.showMessage(message, 'warning', duration)
      },
      // 关闭
      close: () => {
        MessageInstanse.closeMessage()
      }
    }

上面代码呢,我们给Vue原型添加了$Message 对象,对象中编写了我们需要的通知方法,然后呢我们通过通知组件实例 MessageInstanse去调用他的 showMessage 方法去打开通知,closeMessage 方法关闭通知。

打开通知时,第一个参数是通知内容,第二个就是消息类类型,第三个是延时参数

MessageComponent.js全部代码如下:

import Message from './MessageComponent.vue'
let MessageInstanse = null
const MessagePlugin = {
  install(Vue) {
    if (!MessageInstanse) {
      // Vue.extend() 方法创建了一个名为 MessageComponent 的组件构造器。
      const MessageComponent = Vue.extend(Message);
      MessageInstanse = new MessageComponent();
      // 将通知组件挂载到DOM中
      const container = document.createElement("div");
      document.body.appendChild(container);
      MessageInstanse.$mount(container);
    }
    Vue.prototype.$Message = {
      // 加载
      loading: (message, duration = 1000 * 60 * 60 * 24) => {
        MessageInstanse.showMessage(message, 'loading', duration)
      },
      // 成功
      success: (message, duration) => {
        MessageInstanse.showMessage(message, 'success', duration)
      },
      // 失败
      error: (message, duration) => {
        MessageInstanse.showMessage(message, 'error', duration)
      },
      // 警告
      warning: (message, duration) => {
        MessageInstanse.showMessage(message, 'warning', duration)
      },
      // 关闭
      close: () => {
        MessageInstanse.closeMessage()
      }
    }
  }
}
export default MessagePlugin

6、实现两个方法:

在MessageComponent.vue中,组件实现打开和关闭通知的逻辑,使用 setTimeout 定时器,

通知显示与隐藏,使用translate和transition过度动画,代码如下:

<template>
  <div ref="message" class="lx-message">
    <!-- 字体 -->
    <i class="iconfont" :class="iconClass"></i>
    <!-- 消息提示 -->
    <span :class="messageClass">
      {{ message }}
    </span>
  </div>
</template>

<script>
export default {
  name: 'MessageComponent',
  data() {
    return {
      message: '',
      // 类型
      type: '',
      // 事件
      duration: 2000,
      // 计时器
      timer: null,
    }
  },
  computed: {
    // 动态添加类名
    iconClass() {
      // 成功
      if (this.type === 'success') {
        return `icon-correct`
        // 错误
      } else if(this.type === 'error') {
        return `icon-error`
        // 警告
      } else if (this.type === 'warning') {
        return `icon-jinggao-warning`
        // 加载
      } else if (this.type === 'loading') {
        return `icon-refresh rotate`
      }
      return ``
    },
    messageClass() {
      if (this.type === 'success') {
        return `lx-message-content`
      } else if(this.type === 'error') {
        return `lx-message-error`
      } else if(this.type === 'warning') {
        return `lx-message-warning`
      } else if(this.type === 'loading') {
        return `icon-message-refresh`
      }
      return ``
    }
  },
  methods: {
    // 打开的方法
    showMessage(message, type, duration) {
      if(type === 'success') {
        this.type = type;
        this.message = message || '这是一条成功消息'; // 不传message就是默认值
        this.duration = duration || 2000;
      }
      else if (type === 'error') {
        this.type = type;
        this.message = message || '这是一条失败消息';
        this.duration = duration || 2000;
      }
      else if (type === 'warning') {
        this.type = type;
        this.message = message || '这是一条警告消息';
        this.duration = duration || 2000;
      }
      else if (type === 'loading') {
        this.type = type;
        this.message = message || '这是一条加载消息';
        this.duration = duration || 2000;
      }
      // 过渡
      this.$refs.message.style.transform = "translate(-50%,75px)";
      if (this.timer) {
        this.timer = clearTimeout(this.timer);
      }
      this.timer = setTimeout(() => {
        this.closeMessage();
      }, this.duration);
    },
    // 关闭的方法
    closeMessage() {
      if (this.timer) {
        this.timer = clearTimeout(this.timer);
      }
      // 过渡
      this.$refs.message.style.transform = "translate(-50%,0px)";
    }
  }
}
</script>

<style scoped>
@import url('../assets/icon/iconfont.css');
</style>
<style scoped lang="less">
.lx-message {
  max-width: 70%;
  position: fixed;
  height: 25px;
  display: flex;
  align-items: center;
  top: -40px;
  left: 50%;
  transform: translateX(-50%);
  padding: 5px 15px;
  border-radius: 8px;
  text-align: center;
  background-color: #edf7fc;
  border-color: #b9c0c4;
  border: 1px solid transparent;
  transition: 0.55s;
  z-index: 999;
  span {
    margin-left: 5px;
  }
  i {
    &.rotate {
      animation: moveicon 1.5s infinite linear;
    }
  }
}
@keyframes moveicon {
  0% {
    rotate: 0deg;
  }
  100% {
    rotate: 360deg;
  }
}
.icon-correct {
  color: #19be6b;
  font-size: 22px;
}
.lx-message-content {
  color: #19be6b;
}
.icon-error {
  color: #ee3c10;
  font-size: 22px;
}
.lx-message-error {
  color: #ed3f13;
}
.icon-jinggao-warning {
  color: #ff9900;
  font-size: 22px;
}
.lx-message-warning {
  color: #eb8d01;
}
.icon-refresh {
  color: #57c5f7;
  font-size: 22px;
}
.icon-message-refresh {
  color: #57c5f7;
}

</style>

上述showMessage方法中代码都一样。我们可以抽离出一个方法叫base 

 base(type, duration) {
      this.type = type;
      this.duration = duration || 2000;
  },

修改如下:

base(type, duration) {
      this.type = type;
      this.duration = duration || 2000;
    },
    // 打开的方法
    showMessage(message, type, duration) {
      if(type === 'success') {
        this.message = message || '这是一条成功消息';
        this.base(type, duration)
      }
      else if (type === 'error') {
        this.message = message || '这是一条失败消息';
        this.base(type, duration)
      }
      else if (type === 'warning') {
        this.message = message || '这是一条警告消息';
        this.base(type, duration)
      }
      else if (type === 'loading') {
        this.message = message || '这是一条加载消息';
        this.base(type, duration)
      }
      // 过渡
      this.$refs.message.style.transform = "translate(-50%,75px)";
      if (this.timer) {
        this.timer = clearTimeout(this.timer);
      }
      this.timer = setTimeout(() => {
        this.closeMessage();
      }, this.duration);
    }

7、测试组件:

<template>
  <div id="app">
    <lx-button @click="error" size="large" type="error">错误</lx-button>
    <lx-button @click="warning" size="small" type="warning">警告</lx-button>
    <lx-button disabled>禁用</lx-button>
    <lx-button @click="loadingData" type="info">加载</lx-button>
    <lx-button @click="$Message.close()" >关闭</lx-button>
    <lx-button @click="success" size="big" type="success">成功</lx-button>
  </div>
</template>

<script>
export default {
  methods: {
    loadingData() {
      this.$Message.loading('正在加载...')
      this.$api.get('/api/list').then(res => {
        this.$Message.close()
        if(res.status >= 200) {
          this.$Message.success('加载成功...')
          this.message = res.data
        } else {
          this.$Message.error('加载失败...')
        }
      })
    },
    success() {
      this.$Message.success('这是一条成功消息...')
    },
    warning() {
      this.$Message.warning('这是一条警告消息...')
    },
    error() {
      this.$Message.error('这是一条错误消息...')
    }
  }
}
</script>

<style>
</style>

按钮也是自己封装的按钮,根据传递的类型更改按钮的大小尺寸和颜色背景是否禁用。点击对应的按钮会弹出下滑效果的提示,加载按钮的提示图标加了一直旋转的动画更美观,加载成功就会弹出成功提示的消息 点击关闭就会触发关闭的回调

以下是一个基于 Vue3 和 TypeScript 实现自定义 message 的示例: ```html <template> <div> <button @click="showSuccessMessage">Show Success Message</button> <button @click="showErrorMessage">Show Error Message</button> </div> </template> <script lang="ts"> import { defineComponent } from 'vue' interface Message { type: string; content: string; } export default defineComponent({ name: 'CustomMessage', data() { return { messages: [] as Message[] } }, methods: { showMessage(type: string, content: string) { this.messages.push({ type, content }) }, showSuccessMessage() { this.showMessage('success', 'This is a success message.') }, showErrorMessage() { this.showMessage('error', 'This is an error message.') } } }) </script> <style> .message { padding: 10px; margin-bottom: 10px; border-radius: 5px; } .success { background-color: green; color: white; } .error { background-color: red; color: white; } </style> <template> <div> <div v-for="message in messages" :key="message.content" :class="['message', message.type]"> {{ message.content }} </div> </div> </template> ``` 在上述示例中,我们定义了一个 `Message` 接口,用于表示消息的类型和内容。然后,在组件中定义了一个 `messages` 数组,用于存储所有的消息。通过 `showMessage` 方法,我们可以将新的消息添加到 `messages` 数组中。最后,在模板中使用 `v-for` 指令遍历 `messages` 数组,渲染出每条消息。 我们还为消息定义了两种类型:`success` 和 `error`,并为它们分别定义了不同的样式。通过调用 `showSuccessMessage` 和 `showErrorMessage` 方法,我们可以分别显示成功消息和错误消息。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值