vue 全局弹框实现

442 阅读1分钟

1.实现逻辑

  1. 创建工具类create.js,利用Vue实例化,把.vue文件为dom对象
  2. 挂在dom到body上
  3. 组件销毁时候,在body上调用removeChild移除dom对象
  4. 定义Notice.vue,利用create.js挂载全局,并实现显示和定时关闭效果

2.实现代码

//create.js
import Vue from 'vue'

// Component - 组件配置对象
// props - 传递给它的属性
function create(Component, props) {
  // 1.构建Component的实例
  const vm = new Vue({
    render(h) {
      // h是createElement
      // 它可以返回一个vnode
      return h(Component, { props })
    }
  }).$mount() // 不设置挂载目标,依然可以转换vnode为真实节点$el
  // 2.挂载到body上
  //document.body.appendChild(vm.$el)
  document.querySelector(".msgBox").appendChild(vm.$el)//挂载在固定的div上
  // 3.获取组件实例
  const comp = vm.$children[0]

  comp.remove = () => {
    document.body.removeChild(vm.$el)
    vm.$destroy()
  }
  
  return comp
}
export default create

//Notice.vue
<template>
  <div class="box" v-if="isShow">
    <h3>{{title}}</h3>
    <p class="box-content">{{message}}</p>
  </div>
</template>

<script>
export default {
  props: {
    title: {
      type: String,
      default: ""
    },
    message: {
      type: String,
      default: ""
    },
    duration: {
      type: Number,
      default: 1000
    }
  },
  data() {
    return {
      isShow: false
    };
  },
  methods: {
    show() {
      this.isShow = true;
      setTimeout(this.hide, this.duration);
    },
    hide() {
      this.isShow = false;
      this.remove();
    }
  }
};
</script>

<style>
.box  
  width: 100%;
  top: 16px;
  left: 0;
  text-align: center; 
  background-color: #fff;
  border: grey 3px solid; 
} 
</style>

//main.js
Vue.prototype.$notice = function(opts) {
  const comp = create(Notice, opts);
  comp.show();
  return comp;
};

//index.html
<!DOCTYPE html>
<html lang="en">
  <head> 
    <style>
      .msgBox{position:fixed ; width: 100%;}
    </style>
  </head>
  <body>
    <div class="msgBox"></div>
    <div id="app"></div> 
  </body>
</html>

//jform/index.vue
 methods: {
        onClick() {
            this.$refs.submitForm.validate(isVaild => {
                if(isVaild){
                    this.$notice({
                      title : "操作提示",message : "验证成功",
                  }) 
                }else {
                      this.$notice({
                      title : "操作提示",message : "验证失败",
                  })
                }
            });
        }
    },

实现代码2

Vue.extend 实现挂载dom

import Vue from 'vue'
// Component - 组件配置对象
// props - 传递给它的属性
function create(Component, props) {
   //通过参数输入
   const Ctor = Vue.extend(Component); 

   //通过构造函数初始化实例
   const newComp = new Ctor({
       propsData: props
   });
   //平时const vm = new Vue();
  //vm 其实是Vue实例,根实例,对应访问时this.$root
  //vm.chlidren[0] 由于vm只有一个子组件,所有就对应了 App ,也就是根组件
  //vm.chlidren[0] 就是VueComponent的实例化
  //上面代码 newComp 等价于VueComponent的vm.chlidren[0],所以不能再用newComp.chlidren[0]访问子组件
  
   newComp.$mount();//渲染真正dom

   //将组件实例添加到body上
   document.body.appendChild(newComp.$el);
 
   newComp.remove = () => {
       //删除dom
       document.body.removeChild(newComp.$el);
       //销毁组件
       newComp.$destroy();
   }; 
   return newComp;
   
}
export default create