如何写一个全局的Notice组件?

博客 动态
0 285
羽尘
羽尘 2022-06-10 14:00:19
悬赏:0 积分 收藏

如何写一个全局的 Notice 组件?

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

  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-    leave-active-    @after-leave="afterLeave"  >    <div v-if="isShow" >      <div : >        {{          type === "error"            ? "&#127827;"            : type === "success"            ? "&#127808;"            : type === "warn"            ? "&#127819;"            : "&#128051;"        }}        : {{ 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 组件实例移除。

posted @ 2022-06-10 13:19 暮冬有八 阅读(4) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员