赞
踩
像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>

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