本文以封装一个旋转的 Loading 图标为例,讲解如何自定义 Message 动态(这里的“动态”的意思是"会动的")图标。
Element-Plus Message 提供了一个icon
属性,用来自定义图标。icon
属性接受Component
或者String
类型的参数。这个时候,就会想到可以引入 Element-Plus 自带的图标组件:
...
import { Loading } from '@element-plus/icons-vue'
ElMessage({
icon: Loading,
...
});
...
可惜上面这个图标不会动。
Element-Plus 提供了is-loading
CSS Class,只要添加在el-icon
组件上,就能够这个组件旋转起来。
那么我们自己封装旋转的el-icon
成一个自定义组件,就能够让 Message 的图标动起来了:
//新建组件loading.vue
<script setup>
import { Loading } from '@element-plus/icons-vue';
</script>
<template>
<el-icon class="is-loading"><Loading /></el-icon>
</template>
使用上面的组件:
//javascript
import MyLoading from 'loading.vue';
ElMessage({
icon: MyLoading,
...
});
这样就实现了目标,不足就是需要建立一个组件文件。
如果不希望为了实现旋转效果而封装一个自定义组件,还有其他办法可以实现目标。
查看 Message 的源代码(位置在你的项目\node_modules\element-plus\es\utils\vue\icon.mjs
),可以发现,Message 的icon
属性可以接受 3 种类型:
const iconPropType = definePropType([
String,
Object,
Function
]);
String 接受一个不能有特殊字符的字符串,经过 Vue 的 CreateNode 函数处理,会在页面中生成一个以这个字符串命名的标签,例如:
ElMessage({
icon: 'MyTag',
...
});
会在图标应该出现的位置生成一个自定义 HTML 标签:
<MyTag></MyTag>
但暂时没有找到为它添加属性的方法。如果有明白的同学,欢迎通过站内联系方式告诉我,感谢!
最后,还可以传递 Function 类型。Element Message 文档中提到的icon
属性可以是Component
,也就是组件。组件可以是一个符合 Vue 组件格式的 JavaScript 对象,也可以是一个函数。前面的文章(戳这里)讲到了函数式组件,这种组件是一个函数。
所以,可以直接创建一个函数,该函数使用渲染函数h
返回一个组件,最终代码如下:
import { Loading } from '@element-plus/icons-vue';
export const loading = ElMessage({
...
icon: () => {
return h(
'div',
//给任意 HTML 元素增加下面的两个 Class,都会应用旋转效果
//这两个 Class 是 Element-Plus 提供的
//这里这样用仅仅为了方便,也可以自己写动画
{ class: 'el-icon is-loading' },
[h(Loading)]
);
},
//不自动关闭,通过 Message 实例的 close 方法手动关闭
duration: 0,
...
});
这样,一个会显示加载动画的自定义 Message 就实现了。下面是完整的代码,还顺便封装成了一个更方便的工具:
//新建 msg.js
import { h } from 'vue';
import { ElMessage } from "element-plus";
import { Loading } from "@element-plus/icons-vue";
//可以在全局样式中修改 Message 的样式
const customClass = 'el-message-custom';
const duration = 4000;
function msg(message, type = 'message') {
if (type === 'loading') {
return ElMessage({
icon: () => {
return h(
'div',
{ class: 'el-icon is-loading' },
[h(Loading)]
);
},
message,
customClass,
duration: 0,
});
}
ElMessage({ message, type, customClass, duration });
}
export default {
message: message => {
msg(message);
},
success: message => {
msg(message, 'success');
},
warning: message => {
msg(message, 'warning');
},
error: message => {
msg(message, 'error');
},
loading: message => {
return msg(message, 'loading');
}
};
使用:
import msg from 'msg.js'
const loading = msg.loading('提交中,请稍候');
setTimeout(()=>{
loading.close();
msg.success('提交成功');
}, 3000)
End