vue 3.0 封装一个message提示组件

前言

vue2.x中,可以使用 Vue.extends 来封装一个弹框,在vue 3.0中,该api已经被废除。

实现后使用方式: Message.info(‘提示’); Message.error(‘错误’);

1.修改index.html

注: 添加 < div id=“message”></ div>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <div id="message"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

2.新建一个index.ts文件

注:

使用class类方式来写调用方法。当然如果是loading等也可以直接用函数方法实现
createApp(组件) mount(id / class / div), 可以参考main.ts。
h函数第一个参数是组件,第二个是组件的props,第三个是插槽的属性。

import { createApp, h, ref, reactive } from 'vue';
// 注意这里替换成存放路径
import MessageComponent from './MessageComponent.vue';

// 初始消息列表
interface MessageList {
  type: string;
  title: string;
}
const messageList = reactive<MessageList[]>([]);
// 消息显示时长
const timer = ref<number>(3000);

// 处理数据
function handleData(type: string, title: string): void {
  // 数据添加
  messageList.push({ type, title });

  // 数据删除
  setTimeout(() => {
    if (messageList.length > 0) {
      messageList.shift();
    }
  }, timer.value);
  
  // 创建
  const app = createApp({
    render() {
      return h(MessageComponent, { messageList });
    }
  });

  // 容器挂载
    //备注,如果这里没有 #message dom元素,可以动态创建一个,然后挂载
    //const divEle = document.createElement('div')
    //divEle.setAttribute('id', 'customShowLoading')
    // 让我们节点挂载到一个dom元素上
    //document.body.appendChild(divEle)

  app.mount('#message');
}

interface MessageImplements {
  info(title: string): void;
  wraning(title: string): void;
  success(title: string): void;
  error(title: string): void;
}

class MessageClass implements MessageImplements {
  // 普通提示
  info(title: string): void {
    handleData('info', title);
  }

  // 警告提示
  wraning(title: string): void {
    handleData('wraning', title);
  }

  // 成功提示
  success(title: string): void {
    handleData('success', title);
  }

  // 错误提示
  error(title: string): void {
    handleData('error', title);
  }
}

const Message = new MessageClass();

export default Message;

3.MessageComponent.vue, 弹框内容部分

注:< script lang=“ts” setup=“props”></ script> 是 setup(){} 入口函数的语法糖写法(实验性新特性)

<template>
  <ul class="message-list">
    <li
      :class="`message-item ${setClass(item.type)}`"
      v-for="(item, index) in messageList"
      :key="index"
    >
      {{ item.title }}
    </li>
  </ul>
</template>

<script lang="ts" setup="props">
import { reactive } from 'vue';

interface MessageList {
  type: string;
  title: string;
}

declare const props: {
  messageList: {
    type: Array<MessageList[]>;
    default: [];
  };
};

export function setClass(type: string): string {
  if (type === 'info') {
    return 'message-info-item';
  } else if (type === 'wraning') {
    return 'message-wraning-item';
  } else if (type === 'success') {
    return 'message-success-item';
  } else if (type === 'error') {
    return 'message-error-item';
  }

  return '';
}
</script>

<style lang="less" scoped>
.message-list {
  position: fixed;
  top: 24px;
  right: 24px;
  z-index: 1000;
  max- 200px;
  margin-bottom: 0;
  text-align: right;
  .message-item {
    display: inline-block;
    padding: 12px 24px;
    border: 1px solid #b3d0cf;
    margin-left: 8px;
    margin-bottom: 12px;
    background-color: #e6f3ff;
    font-size: 14p;
    color: #007bff;
    text-align: left;
    box-shadow: 0 1px 1px 0 hsla(0, 0%, 80.4%, 0.5);
    border-radius: 2px;
    cursor: default;
  }
  .message-info-item {
    border: 1px solid #b3d0cf;
    background-color: #e6f3ff;
    color: #007bff;
  }
  .message-error-item {
    border: 1px solid #e99;
    background-color: #f6e3e3;
    color: #e33;
  }
}
</style>

4. 使用

<template>
  <button @click="clickMe">点我</button>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
// 注意这里替换成存放路径
import Message from '@components/message/index.ts';

export default defineComponent({
  setup() {
    function clickMe(): void {
      Message.info('详情跳转');
    }
    return {
      clickMe
    };
  }
});
</script>

原文地址:https://www.cnblogs.com/xm0328/p/15217512.html