【vue3】命令式组件封装,message封装示例;(函数式组件?)

46 篇文章 6 订阅
30 篇文章 0 订阅
本文介绍了如何在Vue中创建一个命令式风格的消息提示组件message.vue,包括组件的结构、生命周期钩子以及如何通过API调用显示和关闭消息。作者还讨论了组件封装的不同命名观点。
摘要由CSDN通过智能技术生成

仅做代码示例;当然改进的地方还是不少的,仅作为该类组件封装方式的初步启发;
理想大成肯定是想要像 `饿了么` 这些组件库一样。

有的人叫这函数式组件,有的人叫这命令式组件,我个人还是偏向于命令式组件的称呼。因为以vue官方文档里对函数式组件的描述,该组件不符合相关类型描述。
而且这种主要以`关注实现过程为主`的封装风格,感觉叫 命令式组件 贴切点,欢迎大家提出自身观点!


1、封装 message.vue 消息提示组件;

<template>
  <div :ref="(el) => setRef(el, index)" v-for="(item, index) in showList" :key="item.message + index" class="message"
    :class="[item.type]">
    <span class="messageIcon">∮</span>
    <span>{{ item.message }}</span>
    <span class="closeIcon" @click="closeTarget(index)">×</span>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from "vue";
const props = defineProps({
  closeAll: Function
})

const emit = defineEmits(['close'])
let lastRef = null
function setRef(el, index) {
  console.log(el,index);
  if (el) {
    index ? (lastRef = el) : (lastRef = null) 
    const height = lastRef?.clientHeight || 0
    el.style.top = (20 * (1 + index)) + height + 'px'
  }

}
const showList = ref([])
function createMessage(options) {
  console.log(options, showList);
  showList.value.push({
    ...options,
    timeout: setTimeout(() => {
      showList.value.shift()
      options.onClose()
      if (!showList.value.length) {
        props.closeAll()
      }
    }, 5000)
  })
}
function closeTarget(i) {
  const target = showList.value.splice(i, 1)[0]
  target.onClose()
  clearTimeout(target.timeout)
  if (!showList.value.length) {
    props.closeAll()
  }
}
defineExpose({
  createMessage
})
onMounted(() => {
  console.log(props, 'props内容');
  console.log('命令式组件加载');
})
onUnmounted(() => {
  console.log('命令式组件卸载');
})
</script>

<style scoped lang="less">
.message {
  display: flex;
  align-items: center;
  position: fixed;
  top: 20px;
  left: 50%;
  transform: translate(-50%, 0px);
  border-radius: 5px;
  padding: 15px 20px;
  font-size: 14px;
  background-color: #f4f4f5;
  border: 1px solid #e9e9eb;
  color: #909399;
  z-index: 3000;
  &.success {
    background-color: #f0f9eb;
    border: 1px solid #e1f3d8;
    color: #67c23a;
  }

  .messageIcon {
    width: 16px;
    height: 16px;
    line-height: 16px;
    margin-right: 5px;
  }

  .closeIcon {
    width: 16px;
    height: 16px;
    line-height: 16px;
    margin-left: 10px;
    font-size: 18px;
    cursor: pointer;
  }
}
</style>

2、封装Message函数,在该函数内创建message组件实例、渲染提示信息;

import { createApp } from "vue";
import message from "./message.vue";

let newInstance = null;
export default function Message(options) {
  function onClose() {
    options.onClose && options.onClose();
  }
  if (!newInstance) {
    const el = document.createElement("div");
    const app = createApp(message,{
      closeAll
    });
    const vm = app.mount(el);
    document.body.appendChild(el);
    newInstance = vm;
    newInstance.createMessage({
      ...options,
      onClose,
    });
    function closeAll(){
      app.unmount();
      el.remove();
      newInstance = null;
    }
  } else {
    newInstance.createMessage({
      ...options,
      onClose,
    });
  }
}

 3、正常开发内使用:



import { onMounted, onUnmounted, ref } from "vue";
import messageApi from "@/components/newApi/message";

onMounted(() => {
    setTimeout(() => {
      messageApi({
        type:'success',
        message:'消息内容测试,demo.',
        onClose(){
          console.log('年的槽');
        }
      })
      setTimeout(() => {
        messageApi({
        type:'success',
        message:'消息内容测试,demo222.',
        onClose(){
          console.log('年的槽*2');
        }
      })
      }, 1000);
    }, 1000*3);
})

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值