手写一个弹窗组件 -vue

最近的项目中,需要自己去手写一个全局的弹窗组件,在下面贴出自己的代码。

组件写的比较简单  notice.vue

<template>
  <div class="alert">
    <div class="alert-container" v-for="item in alerts" :key="item.id">
      <div class="alert-content">{{item.content}}</div>
    </div>
  </div>
</template>
<script>
export default {
    name:'notice',
    data() {
        return {
            alerts: []
        }
    },
    created () {
        // id自增控制
        this.id = 0;
    },
    methods: {
        add(options) {
            const id = 'id_' + this.id++;
            const _alert = {...options,id:id};
            this.alerts.push(_alert);
            // 自动关闭
            const duration = options.duration || 1; //单位秒
            setTimeout(() => {
                this.del(id);
            }, duration * 1000);
        },
        del (id){
            for (let i = 0; i< this.alerts.length; i++) {
              const element = this.alerts[i];
              if(element.id === id){
                  this.alerts.splice(i,1);
                  break;
              }
            }
        }
    },

}
</script>

<style  scoped>
    .alert {
  position: fixed;
  width: 100%;
  top: 30px;
  left: 0;
  text-align: center;
 }
  .alert  .alert-content {
    display: inline-block;
    padding: 8px;
    background: #fff;
    margin-bottom: 10px;
  }

</style>

自定义组件的挂载   这里用了两种不同的形式,考虑到不同的组件需要特定的方法,比如notice组件只能是一个单例的模式,所以用了一个notice.js给他挂载,其他通用的组件可以采用第二种方式进行挂载。

  1 将notice挂载到vue实例上,第一种方式

import Notice from '@/components/Notice.vue';
import Vue from 'vue';

// 给Notice 添加一个创建组建实例的方法,可以动态编译自身模版并挂载
Notice.getInstance = props =>{
    // 创建一个Vue实例
    const instance = new Vue({
        render(h){ //渲染函数,用户渲染置顶模版为虚拟DOM
            // 
            return h(Notice,{ props })
        }
    }).$mount(); //执行挂载 ,若不置顶选择器,则模版将被渲染为文档之外的 元素
    // 必须使用原生的DOM操作 插入到文档中
    document.body.appendChild(instance.$el);

    //获取Notice实例
    const notice = instance.$children[0];
    return notice;
     
}
// 设计一个单例模式,全局范围唯一创建一个Notice实例
let msgInstance = null;
function getInstance() {
    msgInstance = msgInstance || Notice.getInstance();
    return msgInstance;
}
// 暴露接口
export default{
    info({duration=2,content= ''}){
        getInstance().add({
            content,
            duration
        });
    }
}

第二种方式 是通用的组件挂载方式 类似与cube-ui自定义组件的方式

import Vue from 'vue';

// 给Notice 添加一个创建组建实例的方法,可以动态编译自身模版并挂载
function create(Component,props) {
    // 创建一个Vue实例
    const instance = new Vue({
        render(h){ //渲染函数,用户渲染置顶模版为虚拟DOM
            // 例 <BallAnim :el="el">
            return h(Component,{ props })
        }
    }).$mount(); //执行挂载 ,若不置顶选择器,则模版将被渲染为文档之外的 元素
    // 必须使用原生的DOM操作 插入到文档中
    document.body.appendChild(instance.$el);

    //获取Notice实例
    const comp = instance.$children[0];
    comp.remove = () => {
        instance.$destory(); //销毁实例,释放内存
    }
    return comp;
     
}
// 暴露接口
export default create;

在main.js调用

import Notice from '@/components/Notice.vue';

import notice from '@/services/notice.js';

Vue.prototype.$notice = notice;

最后就是在使用这个弹窗组件

 // 自定义的方式
      this.$notice.info({
        duration:3,
        content:'消息'
     })

只需要在需要的地方调用这个方法就可以。

另外一种的调用方法

在你需要的组件中 引入 create.js

import create from '@/services/create';

import BallAnim from '@/components/ballAnim.vue';  //自己创建的组件

//创建实例,并调用
 const anim = create(BallAnim,{el});
//组件内自己的方法
    anim.start();
    anim.$on('transtioned', ()=>{
      anim.remove()
    })
发布了5 篇原创文章 · 获赞 1 · 访问量 755

猜你喜欢

转载自blog.csdn.net/qq_37919791/article/details/102947354