代码演示

<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>
presentation

参数

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;

最近更新: