需求背景:
- 老板希望 Message 组件能够手动触发关闭,但是项目使用的组件库是
Ant Design of Vue(1.7.8)
版本的,看了下高版本的也没有直接支持这个功能的属性。 - 再去看了下
element-ui
组件库,发现它是直接支持了的,心里顿时感觉:我去,什么垃圾Ant Design Vue
。
解决方法
-
但是吐槽归吐槽,问题还是得解决的,当时想的是手写一个
message
组件替换掉官方的,直到我看到了这个:
-
诶,好像有点东西,仔细研究一番,发现他是支持使用
VNode
作为显示内容,那只要返回一个带有关闭图标的VNode
不就好了。 -
最终代码实现:
// 封装到一个js文件里面,避免使用时代码累赘
import { message } from 'ant-design-vue';
/*
h: 是content自带的参数,表示createElement
content:文本内容
*/
const createElementVNode = (h, content) => {
// 定义文本内容及样式(这里的样式延用的官方的)
const innerText = h('span', { style: { color: '#4a5970', fontSize: '14px' } }, content);
// 自定义关闭图标
const innerIcon = h('a-icon', {
style: { marginLeft: '10px', color: '#ccc', cursor: 'pointer' },
attrs: { type: 'close' },
on: { click: () => message.destroy() },
});
// 合到一个 VNode 节点中
const container = h('span', {}, [innerText, innerIcon]);
// 最终返回
return container;
};
// 由于 message 有多种状态,这里需要额外处理
const dtMessage = {};
// 给 dtMessage 循环赋值不同类型的 message函数
['error', 'success', 'info', 'warning', 'warn'].forEach((type) => {
dtMessage[type] = (content, duration, onClose) => {
// 处理 message[type](config) 参数为对象类型
if (typeof content === 'object') {
return message[type]({ ...content, content: h => createElementVNode(h, content?.content) });
}
return message[type](h => createElementVNode(h, content), duration, onClose);
};
});
export default dtMessage;
- 如果对
createElementVNode
中的参数h
不熟悉的,可以参考官方文档 createElement 参数 - 实际使用:
import message from '@/components/message/index.js'
message.success('这是可关闭的 message 组件')
- 运行效果: