前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >vue3 手动封装message消息组件

vue3 手动封装message消息组件

原创
作者头像
爆炒鱿鱼
修改2023-10-30 12:48:41
8240
修改2023-10-30 12:48:41
举报

使用场景

如图所示消息提示框组件的使用场景很清楚:

一般用于登录提示或者一些表单提交(网络请求)的状态提示

参考链接: element-ui_Message 消息提示.

封装组件

目录的话 需要对应vue文件和js同级即可,如图所示(我的项目里面命名为tip)

message.vue

代码语言:javascript
复制
<template>
  <div class="pop-message" :style="style[type]" v-show="visible">
    <i class="icon" :class="[style[type].icon]"></i>
    <span class="text">{{ str }}</span>
  </div>
</template>

<script>
import { onMounted, ref } from "vue";
export default {
  name: "popmessage",
  //    这个是传值方法,通过父级组件传入提示状态以及提示文本
  //    可以根据不同业务自定义更多的状态
  props: {
    type: {
      type: String,
      //    success 成功
      //    warn 警告
      //    error 错误
      default: "success",
    },
    str: {
      type: String,
      default: "登陆成功",
    },
  },
  setup() {
        //    定义一个对象,包含三种情况的样式,对象key就是类型字符串
        //    icon图标这一部分省略了,有需要的可以自己加入
    const style = {
      warn: {
        // icon: "icon-warning",
        color: "#E6A23C",
        backgroundColor: "rgb(253, 246, 236)",
        borderColor: "rgb(250, 236, 216)",
      },
      error: {
        // icon: "icon-shanchu",
        color: "#F56C6C",
        backgroundColor: "rgb(254, 240, 240)",
        borderColor: "rgb(253, 226, 226)",
      },
      success: {
        // icon: "icon-queren2",
        color: "#67C23A",
        backgroundColor: "rgb(240, 249, 235)",
        borderColor: "rgb(225, 243, 216)",
      },
    };

    const visible = ref(false);

    onMounted(() => {
      visible.value = true;
    });

    return { style, visible };
  },
};
</script>

<style scoped lang="less">
//    css样式部分可以根据需求自定义
.pop-message {
  position: absolute;
  z-index: 9999;
  left: 50%;
  margin-left: -150px;
  top: 50px;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 300px;
  height: 50px;
  border: 1px solid #e4e4e4;
  background: #f5f5f5;
  color: #999;
  border-radius: 4px;
  //    以下是过渡动画,如不需要可删去亦可改进
  animation: move 0.38s linear forwards;
  @keyframes move {
    0% {
      transform: translate3d(0, -75px, 0);
      opacity: 0.16;
    }

    50% {
      opacity: 0.68;
    }

    100% {
      transform: none;
      opacity: 1;
    }
  }
}
</style>

index.js

代码语言:javascript
复制
//      引入创建虚拟节点和渲染方法
import { createVNode, render } from "vue";
import tip from "./tip.vue";

//      定义一个div容器
const div = document.createElement("div");
//      将定义的容器添加到dom上
document.body.appendChild(div);
//      定义定时器:一定时间后清除
let timer = null;

export default ({ str, type }) => {
  //      调用创建虚拟节点方法
  //      第一个参数为要创建的虚拟节点即编写好的vue组件
  //      第二个参数为props的参数
  const vnode = createVNode(tip, { str, type });
  //      调用渲染方法:将虚拟节点渲染到dom中
  render(vnode, div);
  //      开启定时器,若原先存在则先进行清除
  timer&&clearTimeout(timer);
  timer = setTimeout(() => {
    render(null, div);
  }, 2000);
};

调用方式

按需/局部调用

代码语言:javascript
复制
<script>
import { onMounted } from "vue";
//    在需要用到该组件的页面中引入
import popmessage from "./components/tip/index.js";

export default {
  setup(props, context) {
    onMounted(() => {
    //     直接调用方法名即可
    //    参数type对于组件中设置好的不同状态
    //    参数str对应消息提示文本
    popmessage({ type: "warn", str: "我是提示框" })
    });
    return {};
  },
};
</script>

全局调用

vue3与vue2不同,原先的vue.prototypeAPI已经被弃用,取而代之的是app.config.globalPropertiesAPI在全局目录main.js中进行全局定义,然后在组件中引入即可(其实写到这里,我突然想起来尤大更新的v3版本旨在简化全局定义实际却没有调用到的组件,精简项目大小,对所需组件进行按需引入,所以在vue3中进行全局定义组件,显得有点吃饱撑着了。。。。不过写了就写完了吧)

main.js文件

代码语言:javascript
复制
import { createApp } from 'vue'';
import App from './App.vue';
import router from "./router/index";
//        main.js中引入所需组件
import popmessage from "./components/tip/index.js";

const app = createApp(App);
app.use(router);
app.mount("#app");
//      全局注册组件
app.config.globalProperties.$popmessage = popmessage;

在任意组件中,这里将会使用到getCurrentInstanceAPI获取当前组件实例,相当于vue2中的this另外这个API有些坑,还好我的项目还没有打包上线,这个API直接调用所获取的对象仅适用于生产环境,打包之后不可用,根据以下参考内容,也对应进行改进了打包上线可用的版本,具体如下代码。

任意组件 xx.vue

代码语言:javascript
复制
<script>
import { getCurrentInstance, onMounted } from "vue";

export default {
  setup(props, content) {
    //    注册全局对象,调用全局组件popmessage、
    const {proxy} = getCurrentInstance();
    //    仅适用于生产环境,打包后不可用
   const instance = getCurrentInstance();
   onMounted(()=>{
       //        可用于打包后状态
       proxy.$popmessage({ type: "success", str: "登录成功" });
        //        仅适用于生产环境
     instance.proxy.$popmessage({ type: "success", str: "登录成功" });
   })
    return {};
  },
};

</script>

番外

既然都用到vue3了,**按需引入**的思想早已深入人心,之所以想记录下这个小组件,大多是因为番外的内容。既然vue3的全局调用如此麻烦,远不如局部按需调用,而且又是**将组件封装成一个方法(函数)进行调用**,到此我想到**父子组件传值**进行全局定义,这时候provide/inject这个API就把getCurrentInstance甩了几条街了,话不多说直接看代码。

(以下代码全为个人想法,若有不对或者什么不好的欢迎指出,小弟也是在学习的过程。)

既然是全局调用provide就应该在项目底层的App.vue文件中

代码语言:javascript
复制
<script>
import { onMounted, provide } from "vue";
import popmessage from "./components/tip/index.js";

export default {
  name: "App",
  setup(props, context) {
    onMounted(() => {
      //    包装全局组件为方法,调用方法即可
      provide("popmessage", popmessage);
    });
    return {};
  },
};
</script>

任意组件 xx.vue

代码语言:javascript
复制
<script>
import { onMounted, inject } from "vue";

export default {
  name: "App",
  setup(props, context) {
    onMounted(() => {
     const popmessage = inject("popmessage");
      popmessage({ type: "success", str: "登录成功" })
    });
    return {};
  },
};
</script>

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用场景
  • 封装组件
    • message.vue
      • index.js
      • 调用方式
        • 按需/局部调用
          • 全局调用
          • 番外
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档