ant design vue message 支持可手动关闭

 项目:

vue2 + ant-design-vue1.7.8

需求:

message组件添加可手动关闭功能,效果如下:

85578769dd8e48d8aee7c9dbd73143f6.png

当前message效果:

c957c736d2b342bfb2655d857913d832.png

源码分析:

通过ant design vue源码,了解到Message和Notification底层是同一个组件vc-notification,根据不同配置,实现不同样式和功能。

Nitification组件中有可手动关闭的图标,Message组件中可手动关闭的图标被阉割了。

Nitification源码:

ant-design-vue/es/notification/index.js

d91bafb81c644dde87c8335a2fd4c1ef.png

522e337837a945cb837ace19afa4ab17.png

Message源码:

ant-design-vue/es/message/index.js

5740c90e29d141058ef2c7b752cbab71.png

 be5211047c3843c480466c01b5f317c4.png

 Message源码中没有关闭图标和是否可关闭的属性。

方案:

项目中添加一个myMessage.js文件,抄一份message源码,添加上关闭图标和是否可关闭属性

修改后代码如下:

import _extends from 'babel-runtime/helpers/extends';
import Notification from 'ant-design-vue/es/vc-notification';
import Icon from 'ant-design-vue/es/icon';

var defaultDuration = 3;
var defaultTop = void 0;
var messageInstance = void 0;
var key = 1;
var prefixCls = 'ant-message';
var transitionName = 'move-up';
var getContainer = function getContainer() {
  return document.body;
};
var maxCount = void 0;

function getMessageInstance(callback) {
  if (messageInstance) {
    callback(messageInstance);
    return;
  }
  Notification.newInstance({
    prefixCls: prefixCls,
    transitionName: transitionName,
    // 覆盖原来的样式
    style: {
      top: defaultTop
    },
    getContainer: getContainer,
    maxCount: maxCount,
    // 添加关闭图标
    closeIcon: function closeIcon(h) {
      var closeIconToRender = h(
        'span', {
          'class': prefixCls + '-close-x'
        },
        [h(Icon, {
          'class': prefixCls + '-close-icon',
          attrs: {
            type: 'close'
          }
        })]
      );
      return closeIconToRender;
    }
  }, function (instance) {
    if (messageInstance) {
      callback(messageInstance);
      return;
    }
    messageInstance = instance;
    callback(instance);
  });
}

// type NoticeType = 'info' | 'success' | 'error' | 'warning' | 'loading';

function notice(args) {
  var duration = args.duration !== undefined ? args.duration : defaultDuration;
  var iconType = {
    info: 'info-circle',
    success: 'check-circle',
    error: 'close-circle',
    warning: 'exclamation-circle',
    loading: 'loading'
  } [args.type];

  var target = args.key || key++;
  var closePromise = new Promise(function (resolve) {
    var callback = function callback() {
      if (typeof args.onClose === 'function') {
        args.onClose();
      }
      return resolve(true);
    };
    getMessageInstance(function (instance) {
      instance.notice({
        key: target,
        // 添加是否可关闭属性
        closable: true,
        duration: duration,
        style: {},
        content: function content(h) {
          var iconNode = h(Icon, {
            attrs: {
              type: iconType,
              theme: iconType === 'loading' ? 'outlined' : 'filled'
            }
          });
          var switchIconNode = iconType ? iconNode : '';
          return h(
            'div', {
              'class': prefixCls + '-custom-content' + (args.type ? ' ' + prefixCls + '-' + args.type : '')
            },
            [args.icon ? typeof args.icon === 'function' ? args.icon(h) : args.icon : switchIconNode, h('span', [typeof args.content === 'function' ? args.content(h) : args.content])]
          );
        },
        onClose: callback
      });
    });
  });
  var result = function result() {
    if (messageInstance) {
      messageInstance.removeNotice(target);
    }
  };
  result.then = function (filled, rejected) {
    return closePromise.then(filled, rejected);
  };
  result.promise = closePromise;
  return result;
}

// type ConfigContent = React.ReactNode | string;
// type ConfigDuration = number | (() => void);
// export type ConfigOnClose = () => void;

function isArgsProps(content) {
  return Object.prototype.toString.call(content) === '[object Object]' && !!content.content;
}

// export interface ConfigOptions {
//   top?: number;
//   duration?: number;
//   prefixCls?: string;
//   getContainer?: () => HTMLElement;
//   transitionName?: string;
// }

var api = {
  open: notice,
  config: function config(options) {
    if (options.top !== undefined) {
      defaultTop = options.top;
      // delete messageInstance for new defaultTop
      messageInstance = null;
    }
    if (options.duration !== undefined) {
      defaultDuration = options.duration;
    }
    if (options.prefixCls !== undefined) {
      prefixCls = options.prefixCls;
    }
    if (options.getContainer !== undefined) {
      getContainer = options.getContainer;
    }
    if (options.transitionName !== undefined) {
      transitionName = options.transitionName;
      // delete messageInstance for new transitionName
      messageInstance = null; 
    }
    if (options.maxCount !== undefined) {
      maxCount = options.maxCount;
      messageInstance = null;
    }
  },
  destroy: function destroy() {
    if (messageInstance) {
      messageInstance.destroy();
      messageInstance = null;
    }
  }
};

['success', 'info', 'warning', 'error', 'loading'].forEach(function (type) {
  api[type] = function (content, duration, onClose) {
    if (isArgsProps(content)) {
      return api.open(_extends({}, content, {
        type: type
      }));
    }
    if (typeof duration === 'function') {
      onClose = duration;
      duration = undefined;
    }
    return api.open({
      content: content,
      duration: duration,
      type: type,
      onClose: onClose
    });
  };
});

api.warn = api.warning;

export default api;

组件中引入及使用:

<template>
  <div>
    <a-button @click="openMessage">Message</a-button>
    <a-button @click="openNotification">Notification</a-button>
  </div>
</template>
<script>
import myMessage from "@/views/component/myMessage";
export default {
  data() {
    return {};
  },
  methods: {
    openMessage() {
      myMessage.info({ duration: 3, content: "这是一条info提示" });
      myMessage.success({ duration: 3, content: "这是一条success提示" });
      myMessage.error({ duration: 3, content: "这是一条error提示" });
      myMessage.warning({ duration: 3, content: "这是一条warning提示" });
      myMessage.warn({
        duration: 3,
        content:
          "这是一条warn提示 This is the content of the notification. This is the content of the notification. This is the content of the notification."
      });
    },
    openNotification() {
      this.$notification.success({
        duration: 10000,
        message: "Notification Title",
        description:
          "This is the content of the notification. This is the content of the notification. This is the content of the notification.",
        onClick: () => {
          console.log("Notification Clicked!");
        }
      });
    }
  }
};
</script>

全局引入的,可做如下配置:

import myMessage from "@/views/component/myMessage";
Vue.prototype.$message = myMessage;

实现效果如下:

543050bed62e443398d95bc4d48730a6.png

这时关闭图标是不能点击的,

需要在全局样式中添加

.ant-message-notice-close {
    pointer-events: all;
}

这样关闭图标就可以正常使用了。

样式再稍加调整,就可以实现如下效果了。

 

8881f40b2c1a440788e778a0fe9a6e6a.png

 

5e33c80b96ad422fa60c3cd1c77d9139.png

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
您好!对于Vue仿写$message的功能,我可以为您提供一些指导。在Vue中,您可以使用以下步骤来实现类似的消息提示功能: 1. 创建一个名为Message的全局组件,用于显示消息提示。您可以在项目的根目录下创建一个名为Message.vue的文件。 2. 在Message组件中,定义一个data属性来存储要显示的消息内容和类型。例如,您可以使用一个数组来存储多个消息对象,每个对象包含消息内容和类型属性。 3. 在Message组件的模板中,使用v-for指令循环遍历消息数组,并根据每个消息的类型动态设置样式。 4. 在主应用程序中,使用Vue的全局方法或插件来触发和管理消息提示。例如,您可以创建一个名为$notify的方法,接受消息内容和类型作为参数,并将这些参数添加到Message组件的消息数组中。 以下是一个简单的示例: ```html <!-- Message.vue --> <template> <div class="message-container"> <div v-for="message in messages" :key="message.id" :class="message.type"> {{ message.content }} </div> </div> </template> <script> export default { data() { return { messages: [] }; } }; </script> <style> .error { color: red; } .success { color: green; } </style> ``` ```javascript // main.js import Vue from 'vue'; import Message from './Message.vue'; Vue.prototype.$notify = function(content, type) { const message = { id: Date.now(), content, type }; Vue.$root.$children[0].messages.push(message); }; new Vue({ render: h => h(App) }).$mount('#app'); ``` 然后,您可以在整个应用程序中使用`this.$notify(content, type)`来触发消息提示,例如: ```javascript this.$notify('操作成功', 'success'); this.$notify('请求失败', 'error'); ``` 请注意,这只是一个简单的示例,您可以根据实际需求来扩展和定制这个Message组件。希望对您有所帮助!如果您有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值