下面将会实现这样的效果:

  1. 组件动态创建脚本:

    NotificationBanner.js

    import Vue from "vue";
    import Notice from "@/components/Noticer/Notice.vue"; function create(Component, props) {
    // 先建立实例
    const vm = new Vue({
    render(h) {
    //h就是createElement,它返回VNode
    return h(Component, { props });
    },
    }).$mount();
    // 手动挂载 // 判断是否存在container,如果不存在则先创建
    let container;
    container = document.querySelector(".noticer-container");
    if (container == null) {
    container = document.createElement("div");
    container.classList.add("noticer-container");
    container.style.position = "fixed";
    container.style.top = "50px";
    container.style.right = "0px";
    container.style.overflow = "hidden";
    container.style.zIndex = 9999; document.body.appendChild(container);
    } container.appendChild(vm.$el); //销毁方法
    const comp = vm.$children[0];
    comp.remove = function () {
    container.removeChild(comp["$el"]);
    vm.$destroy();
    };
    comp.show();
    return comp;
    } Vue.prototype.$notice = {
    error: function (props) {
    create(Notice, Object.assign(props, { type: "error" }));
    },
    info: function (props) {
    create(Notice, Object.assign(props, { type: "info" }));
    },
    success: function (props) {
    create(Notice, Object.assign(props, { type: "success" }));
    },
    warn: function (props) {
    create(Notice, Object.assign(props, { type: "warn" }));
    },
    };

    这里有一些值得注意的地方:

    1. container: 的作用是notice的容器,它可以用于定位notice在页面的哪里展示,注意notice不应该随页面卷动,因此其定位是fixed, 而之所以设定为 overflow:hidden 的原因则是,notice 在出现和移除的时候,发生的动画偏移,会让页面出现横向滚动条。为了避免重复创建container, 这里做了一个判断逻辑。然后所有动态生成的notice实例dom都会通过 appendChild 添加到这个容器。
    2. 在移除的时候, 移除的是 vm.$children[0]["$el"] , 原因是,Notice 模板的实现中,外层套了一个 transition , 而这个transition是并不会渲染dom的。
  2. 创建Notice组件模板:

    组件模板

    <template>
    <transition
    enter-active-class="animate__animated animate__slideInRight"
    leave-active-class="animate__animated animate__slideOutRight"
    @after-leave="afterLeave"
    >
    <div v-if="isShow" class="notice__root">
    <div :class="`notice-type-${type}`" class="noticer">
    {{
    type === "error"
    ? "🍓"
    : type === "success"
    ? "🍀"
    : type === "warn"
    ? "🍋"
    : "🐳"
    }}
    : {{ message }}
    </div>
    </div>
    </transition>
    </template>
    <script>
    export default {
    props: {
    title: {
    type: String,
    default: "",
    },
    message: {
    type: String,
    default: "",
    },
    time: {
    type: Number,
    default: 1000,
    },
    type: {
    type: String,
    },
    },
    data() {
    return {
    isShow: false,
    };
    },
    methods: {
    show() {
    this.isShow = true;
    setTimeout(this.hide, this.time);
    },
    hide() {
    this.isShow = false;
    },
    afterLeave() {
    this.remove();
    },
    },
    };
    </script>
    <style lang="less" scoped>
    @error: rgb(255, 30, 30);
    @warn: rgb(240, 192, 0);
    @success: rgb(0, 144, 74);
    @info: rgb(0, 80, 218); @errorBg: rgb(255, 208, 208);
    @warnBg: rgb(255, 245, 207);
    @successBg: rgb(210, 255, 233);
    @infoBg: rgb(203, 222, 255); .notice__root {
    user-select: none;
    padding: 5px 50px 5px 5px;
    } .noticer {
    padding: 5px 20px;
    margin: 10px 0px;
    // margin-right: 50px;
    border-radius: 8px;
    font-size: 16px;
    width: auto;
    min-width: 280px;
    max-width: 300px;
    word-break: break-all;
    text-align: center;
    box-sizing: border-box;
    }
    .notice-type-error {
    color: @error !important;
    border: 2px solid @error;
    box-shadow: 1px 1px 5px 2px @errorBg;
    background-color: @errorBg; // border: 1px solid red;
    }
    .notice-type-warn {
    color: @warn !important;
    border: 2px solid @warn;
    background-color: @warnBg;
    box-shadow: 1px 1px 5px 2px @warnBg;
    }
    .notice-type-success {
    color: @success !important;
    border: 2px solid @success;
    background-color: @successBg;
    box-shadow: 1px 1px 5px 2px @successBg;
    }
    .notice-type-info {
    color: @info !important;
    border: 2px solid @info;
    background-color: @infoBg;
    box-shadow: 1px 1px 5px 2px @infoBg;
    }
    </style>
  3. main.js 中引入执行该脚本即可

    import Vue from "vue";
    import App from "./App.vue";
    import "animate.css";
    import "@/components/Noticer/NotificationBanner.js"; new Vue({
    render: (h) => h(App),
    }).$mount("#app");
  4. 代码中使用实例:

    if (!this.nickname) {
    this.$notice.error({
    message: "好汉!姓甚名谁?",
    time: 3000,
    });
    } else {
    this.showModal = false;
    this.$notice.info({
    message: this.nickname + "来了!!!",
    time: 3000,
    });
    }

动态创建组件的执行逻辑:

当在使用的时候:

this.$notice.error({
message: "好汉!姓甚名谁?",
time: 3000,
});

上方代码触发,实际上会触发 NotificationBanner.js 中的 create函数,该函数创建了一个notice 的组件实例,并在实力上添加了一个remove 方法,然后直接触发组件中的 show 方法。

notice 模板实例中:

methods: {
show() {
this.isShow = true;
setTimeout(this.hide, this.time);
},
hide() {
this.isShow = false;
},
afterLeave() {
this.remove();
},
},

show 方法执行,除了展示 notice,立即设定一个延时函数执行 hide 方法。

hide 方法执行, vue 提供的 transition 钩子 afterleave() 会在移除动画执行完毕后触发。 这时候,去触发 remove 方法,将该notice 组件实例移除。

如何写一个全局的 Notice 组件?的更多相关文章

  1. 手写一个简单的starter组件

    spring-boot中有很多第三方包,都封装成starter组件,在maven中引用后,启动springBoot项目时会自动装配到spring ioc容器中. 思考: 为什么我们springBoot ...

  2. Tsx写一个通用的button组件

    一年又要到年底了,vue3.0都已经出来了,我们也不能一直还停留在过去的js中,是时候学习并且在项目中使用一下Ts了. 如果说jsx是基于js的话,那么tsx就是基于typescript的 废话也不多 ...

  3. python安装及写一个简单的验证码组件(配合node)

    1.安装Python 到官网下载响应系统的版本(这里以windows为例):https://www.python.org/downloads/windows/ 然后就是不断地"下一步&quo ...

  4. Vue学习—Vue写一个图片轮播组件

    1.先看效果: 熟悉的图片轮播,只要是个网站,百分之90以上会有个图片轮播.我认为使用图片轮播. 第一可以给人以一种美观的感受,而不会显得网站那么呆板, 第二可以增加显示内容,同样的区域可以显示更多内 ...

  5. 用vue2.x注册一个全局的弹窗alert组件

    一.在实际的开发当中,弹窗是少不了的,默认系统的弹窗样式太丑,难以满足项目的实际需求,所以需要自己定义弹窗组件,把弹窗组价定义为全局的,这样减少每次使用的时候引入麻烦,节省开发时间.本文将分享如何定义 ...

  6. 用vue2.x注册一个全局的弹窗alert组件、confirm组件

    一.在实际的开发当中,弹窗是少不了的,默认系统的弹窗样式太丑,难以满足项目的实际需求,所以需要自己定义弹窗组件,把弹窗组价定义为全局的,这样减少每次使用的时候引入麻烦,节省开发时间.本文将分享如何定义 ...

  7. react全局的公共组件-------弹框 (Alert)

    最近研究react,发现写一个组件很容易,但是要写一个全局的好像有点麻烦.不能像VUE一样,直接在原型上面扩展,注册全局组件 下面实现一个弹框,只需要引入之后,直接调用方法即可,不需要写入组件 给出我 ...

  8. 如何优雅的写一个Vue 的弹框

    写Vue或者是react 都会遇见弹框的问题.也尝试了多种办法来写弹框,一直都不太满意,今天特地看了一下 Element UI 的源码,模仿着写了一个简易版. 大概有一下几个问题: 1.弹框的层级问题 ...

  9. 从零开始写一个npm包,一键生成react组件(偷懒==提高效率)

    前言 最近写项目开发新模块的时候,每次写新模块的时候需要创建一个组件的时候(包含组件css,index.js,组件js),就只能会拷贝其他组件修改名称 ,但是写了1-2个后发现效率太低了,而且极容易出 ...

随机推荐

  1. 彻底理解synchronized

    1. synchronized简介 在学习知识前,我们先来看一个现象: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public ...

  2. 在react项目中使用redux-thunk,react-redux,redux;使用总结

    先看是什么,再看怎么用: redux-thunk是一个redux的中间件,用来处理redux中的复杂逻辑,比如异步请求: redux-thunk中间件可以让action创建函数先不返回一个action ...

  3. Mybatis实现多级菜单查询

    写在前面 最近实现一个小需求,前端需要菜单的信息,需要向后端发起获取菜单的请求,菜单又是一个多级菜单,后端我用的mybatis进行数据库查询,实现的方法我这里想到有两种,欢迎大家补充. 1. 在Men ...

  4. 正则表达式小技巧,sql中in的字符串处理

    工作中我经常写sql,当写带in的语句时,需要敲好多单引号,逗号,敲写起来容易易出错.因此,我写了一个小工具,处理这种繁琐工作.原理简单,利用正则表达式匹配.替换. 先看界面,一个html页面,包含三 ...

  5. 面试官:请分析一条SQL的执行

    最近一直在写<手撕MySQL系列>文章,我发现自己的切入点有一些问题,虽尝试深入探究MySQL中的一些关键特性,但对于MySQL的知识掌握不太能够形成较好的体系化的知识网络.我感到在对全局 ...

  6. k8s 新版本 部署 Ingress-nginx controller

    k8s 新版本 部署 Ingress-nginx controller 本篇主要记录一下 k8s 新版本 1.23.5 中如何搭建 ingress controller 以及里面的注意项 新版本和老版 ...

  7. 关于LVS中默认的DR模型图

    虽然常用,但是关于DR模型最大的一个缺点就是Director和RS必须在同一个网络中,通过交换机连接,中间不能有路由

  8. python学习-Day35

    目录 今日内容详细 代码创建进程 创建进程的方式 第一种创建进程的方式 创建进程的第二种方式 进程实现并发 join方法 进程间数据默认隔离 进程对象属性和方法 进程号如何查看 查看进程号的方法 杀死 ...

  9. 搭建PWN学习环境

    环境清单 系统环境 Ubuntu22.04 编写脚本 pwntools ZIO 调试 IDA PRO gdb pwndbg ROP工具 checksec ROPgadget one_gadget Li ...

  10. 为什么不建议给MySQL设置Null值?《死磕MySQL系列 十八》

    大家好,我是咔咔 不期速成,日拱一卒 之前ElasticSearch系列文章中提到了如何处理空值,若为Null则会直接报错,因为在ElasticSearch中当字段值为null时.空数组.null值数 ...