代码演示
<template>
<div class="demo-notify">
<Button type="success" @click="notifySuccess">Success</Button>
<Button type="info" @click="notifyInfo">Info</Button>
<Button type="warning" @click="notifyWarn">Warn</Button>
<Button type="danger" @click="notifyError">Error</Button>
<Button type="info" @click="notifyCustom">Custom</Button>
</div>
</template>
<script>
import Notify from "./index";
export default {
methods: {
notifySuccess() {
Notify.success("成功提示");
},
notifyInfo() {
Notify.info("信息提示");
},
notifyWarn() {
Notify.warn("警告提示");
},
notifyError() {
Notify.error("失败提示");
},
notifyCustom() {
Notify.custom({
type: "success",
content: "时间为5s",
duration: 5000,
});
},
},
};
</script>
<style lang="scss">
.demo-notify {
padding: 10px 0;
> * {
margin-right: 20px;
margin-bottom: 20px;
}
}
</style>

参数
Cannot read property 'content' of null
源码
import {
createApp,
Teleport,
ComponentPublicInstance,
defineComponent,
PropType,
TransitionGroup,
} from "vue";
import {
NotifyOption,
NotifyType,
NotifyParams,
NotifyCustomOption,
NotifyCustom,
NotifyConfig,
} from "./types";
import Icon from "../Icon";
import "./index.scss";
const DURING_DEFAULT = 2000;
let notifyWrapper: ComponentPublicInstance<any>;
let seed = 1;
const NotifyApp = defineComponent({
name: "NotifyApp",
props: {
options: {
type: Array as PropType<NotifyConfig[]>,
required: true,
},
},
setup(props) {
const getIconType = (type?: NotifyType) => {
switch (type) {
case NotifyType.SUCCESS:
return "ok-o";
case NotifyType.INFO:
return "info";
case NotifyType.WARN:
return "info";
case NotifyType.ERROR:
return "close-o";
default:
return "info";
}
};
return () => (
<TransitionGroup>
{props.options.map((item) => (
<div
key={item.ref}
class={[
"Notify",
{
"Notify-success": item.type === NotifyType.SUCCESS,
"Notify-info": item.type === NotifyType.INFO,
"Notify-warn": item.type === NotifyType.WARN,
"Notify-error": item.type === NotifyType.ERROR,
},
]}
>
<Icon class="Notify-icon" type={getIconType(item.type)} />
<div class="Notify-content">{item.content}</div>
</div>
))}
</TransitionGroup>
);
},
});
const startNotify = (options: NotifyOption) => {
if (!notifyWrapper) {
notifyWrapper = createApp({
data() {
return {
notifyList: [],
};
},
methods: {
appendOption(config: NotifyConfig) {
this.notifyList.push(config);
},
removeOption(config: NotifyConfig) {
this.notifyList = this.notifyList.filter(
(item: NotifyConfig) => item.ref !== config.ref
);
},
},
render() {
return (
<Teleport to="body">
<div class="Notify-wrapper">
<NotifyApp options={this.notifyList} />
</div>
</Teleport>
);
},
}).mount(document.createElement("div"));
}
const currentSeed = seed++;
const config = {
...options,
ref: currentSeed,
};
notifyWrapper.appendOption(config);
setTimeout(() => {
notifyWrapper.removeOption(config);
}, options.duration || DURING_DEFAULT);
};
const Notify = {
info: (options: NotifyParams) => {
if (typeof options === "string") {
startNotify({
content: options,
type: NotifyType.INFO,
});
} else {
startNotify({
...options,
type: NotifyType.INFO,
});
}
},
success: (options: NotifyParams) => {
if (typeof options === "string") {
startNotify({
content: options,
type: NotifyType.SUCCESS,
});
} else {
startNotify({
...options,
type: NotifyType.SUCCESS,
});
}
},
warn: (options: NotifyParams) => {
if (typeof options === "string") {
startNotify({
content: options,
type: NotifyType.WARN,
});
} else {
startNotify({
...options,
type: NotifyType.WARN,
});
}
},
error: (options: NotifyParams) => {
if (typeof options === "string") {
startNotify({
content: options,
type: NotifyType.ERROR,
});
} else {
startNotify({
...options,
type: NotifyType.ERROR,
});
}
},
custom: (options: NotifyCustomOption) => {
const type = NotifyCustom[options.type];
startNotify({
...options,
type,
});
},
};
export default Notify;