vue自定义插件封装示例

1、实现message插件封装(类似简易版的elementUi的message)

  message组件


<template>
    <transition name="msgbox-fade" @after-leave="handleAfterLeave">
        <div
            :class="[
                'message_wrapper',
                { success: type === 'success' },
                { warning: type === 'warning' },
                { error: type === 'error' },
                { info: type === 'info' },
            ]"
            v-show="visible"
            :style="{ top: styleTop + 'px' }"
        >
            {{ message }}
        </div>
    </transition>
</template> <script>
export default {
    name: 'message',
    data() {
        return {
            // 提示消息文本
            message: '',
            // 类型
            type: '',
            // 显示/隐藏
            visible: false,
            // 定位高度
            styleTop: 20,
        }
    },
    methods: {
        /**
         * @description: message显示
         */
        messageShow() {
            this.visible = true
        },         /**
         * @description: message隐藏
         */
        messageHide() {
            this.visible = false
        },         /**
         * @description: 销毁组件
         */
        handleAfterLeave() {
            this.$destroy(true)
            this.$el.parentNode.removeChild(this.$el)
        },
    },
}
</script> <style scoped lang="scss">
.message_wrapper {
    position: fixed;
    min-width: 380px;
    left: 50%;
    z-index: 99999;
    color: #fff;
    padding: 15px 15px 15px 20px;
    font-size: 14px;
    border-radius: 4px;
    top: 20px;
    transform: translateX(-50%);
    background: #fff;
    color: #909399;
    box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
    line-height: 1;
    &.success{
        background: mix(#ffffff, #67C23A, 90%);
        color: #67C23A;
    }
    &.warning{
        background: mix(#ffffff, #E6A23C, 90%);
        color: #E6A23C;
    }
    &.error{
        background: mix(#ffffff, #F56C6C, 90%);
        color: #F56C6C;
    }
    &.info{
        background: mix(#ffffff, #909399, 90%);
        color: #909399;
    }
    i {
        margin-right: 4px;
    }
}
.msgbox-fade-enter-active {
    -webkit-animation: msgbox-fade-in 0.3s;
    animation: msgbox-fade-in 0.3s;
}
.msgbox-fade-leave-active {
    -webkit-animation: msgbox-fade-out 0.3s;
    animation: msgbox-fade-out 0.3s;
}
@keyframes msgbox-fade-in {
    0% {
        transform: translate3d(-50%, -20px, 0);
        opacity: 0;
    }
    100% {
        transform: translate3d(-50%, 0, 0);
        opacity: 1;
    }
}
@keyframes msgbox-fade-out {
    0% {
        transform: translate3d(-50%, 0, 0);
        opacity: 1;
    }
    100% {
        transform: translate3d(-50%, -20px, 0);
        opacity: 0;
    }
}
</style>

然后书写对应的message.js


import Vue from 'vue'
import messageComponent from './index.vue' const messageConstructor = Vue.extend(messageComponent)
let instances = []
let seed = 1
function messageFun(obj) {
    let { message, type, duration } = obj
    const messageDom = new messageConstructor({
        el: document.createElement('div'),
        data() {
            return {
                message: message,
                type: type,
            }
        },
    })
    let id = 'my_message_' + seed++
    let styleTop = 20
    document.body.appendChild(messageDom.$el)
    messageDom.id = id
    instances.forEach(item => {
        styleTop += item.$el.offsetHeight + 16
    })
    messageDom.styleTop = styleTop
    messageDom.messageShow()
    instances.push(messageDom)
    // 过了 duration 时间后隐藏
    duration = duration ? duration : 3000
    setTimeout(() => {
        let len = instances.length
        messageDom.messageHide()
        let removedHeight = messageDom.$el.offsetHeight
        let index = instances.findIndex(e => e.id === messageDom.id)
        if (len > 1) {
            for (let i = index; i < len; i++) {
                let dom = instances[i].$el
                dom.style['top'] =
                    parseInt(dom.style['top'], 10) - removedHeight - 16 + 'px'
            }
        }
        instances.splice(index, 1)
    }, duration)
} function message() {
    window.$message = Vue.prototype.$message = messageFun
}
export default message

然后在main.ts中注册

// 自定义toast插件
import message from '@/components/notice/message/index.js'
vue.use(message)

然后就可以在全局地方使用

this.$message({message:"成功",type:'success'})

类似效果如下

  

2、实现$confirm插件封装(类似简易版的elementUi的messageBox)

  主要用于操作的二次确定

还是一样,首先书写confirm组件

这里按钮点击事件设置一个callback回调,用于方便后面的操作交互

<template>
    <transition name="confirmbox-fade">
        <div
            class="confirm_wrapper"
            v-show="visible"
            @click="otherClick"
        >
            <div class="confirm_box" ref="confirmBox">
                <p class="confirm_title">
                    <span class="sign"></span>
                    {{ title || "提示" }}
                </p>
                <p class="content_text">
                    {{ message }}
                </p>
                <div class="footer_button">
                    <div class="button" @click="cancel">取消</div>
                    <div class="button define" @click="define">确定</div>
                </div>
            </div>
        </div>
    </transition>
</template>
<script>
export default {
    name: 'Confirm',
    data() {
        return {
            // 标题(默认 提示)
            title: '',
            // 提示文本
            message: '',
            // 显示或隐藏
            visible: false,
        }
    },
    methods: {
        /**
         * @description: 其他地方点击隐藏弹框
         */
        otherClick(e) {
            let confirmBox = this.$refs.confirmBox
            if (e.target.contains(confirmBox)) {
                this.cancel()
            }
        },
        /**
         * @description: 移出
         */
        close() {
            this.visible = false
            setTimeout(() => {
                this.$el.parentNode.removeChild(this.$el)
            }, 300)
        },
        /**
         * @description: 确定
         */
        define() {
            this.close()
            this.callback('confirm')
        },
        /**
         * @description: 取消
         */
        cancel() {
            this.close()
            this.callback('cancel')
        },
    },
}
</script>
<style lang="scss" scoped>
.confirm_wrapper {
    position: fixed;
    top: 0;
    bottom: 0;
    right: 0;
    left: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 99999;
    .confirm_box {
        width: 360px;
        padding-bottom: 10px;
        vertical-align: middle;
        background-color: #fff;
        border-radius: 4px;
        border: 1px solid #ebeef5;
        box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
        text-align: left;
        overflow: hidden;
        backface-visibility: hidden;
        .confirm_title {
            display: flex;
            align-items: center;
            height: 50px;
            line-height: 50px;
            padding-left: 8px;
            font-size: 18px;
            .sign {
                height: 15px;
                width: 4px;
                border-radius: 4px;
                margin-right: 8px;
            }
        }
        .content_text {
            padding: 15px 15px 10px 30px;
            color: #606266;
            font-size: 14px;
        }
        .footer_button {
            display: flex;
            justify-content: flex-end;
            padding-top: 24px;
            padding-right: 24px;
            .button{
                line-height: 1;
                cursor: pointer;
                background: #fff;
                border: 1px solid #dcdfe6;
                color: #606266;
                text-align: center;
                box-sizing: border-box;
                transition: .1s;
                padding: 12px 20px;
                font-size: 14px;
                border-radius: 4px;
                &.define{
                    margin-left: 20px;
                    color: #fff;
                    background-color: #409eff;
                    border-color: #409eff;
                }
            }
        }
    }
}
</style>
<style lang="scss" scoped>
.confirmbox-fade-enter-active {
    -webkit-animation: confirmbox-fade-in 0.3s;
    animation: confirmbox-fade-in 0.3s;
}
.confirmbox-fade-leave-active {
    -webkit-animation: confirmbox-fade-out 0.3s;
    animation: confirmbox-fade-out 0.3s;
}
@keyframes confirmbox-fade-in {
    0% {
        transform: translate3d(0, -20px, 0);
        opacity: 0;
    }
    100% {
        transform: translate3d(0, 0, 0);
        opacity: 1;
    }
}
@keyframes confirmbox-fade-out {
    0% {
        transform: translate3d(0, 0, 0);
        opacity: 1;
    }
    100% {
        transform: translate3d(0, -20px, 0);
        opacity: 0;
    }
}
</style>

对应的书写index.js

这里使用Promise来为用户点击确定或者取消做对应的交互触发

import Vue from 'vue'
import ConfirmBox from './index.vue'
const ConfirmBoxConstructor = Vue.extend(ConfirmBox)
let instance
const initInstance = (message, title) => {
    instance = new ConfirmBoxConstructor({
        el: document.createElement('div'),
        data() {
            return {
                title,
                message,
            }
        },
    })
}
const showConfirm = obj => {
    let { message, title } = obj
    return new Promise((reslove, reject) => {
        initInstance(message, title)
        instance.callback = action => {
            if (action === 'confirm') {
                reslove()
            } else if (action === 'cancel') {
                reject()
            }
        }
        document.body.appendChild(instance.$el)
        Vue.nextTick(() => {
            instance.visible = true
        })
    })
}
function registryConfirm() {
    Vue.prototype.$confirm = showConfirm
}
export default registryConfirm

接下来在main.js中

// 自定义confirm插件
import messageBox from '@/components/notice/messageBox/index.js'
vue.use(messageBox)

然后就可以在全局使用

 this.$confirm({
    message: '弹窗测试'
 })
   .then(() => {})
   .catch(() => {});

类似效果如下

这时,点击确定按钮就会触发 .then里的事件,点击取消则触发 .catch里的事件

typescript对应的声明文件

如果插件是用typescript书写的,则以下是对应的声明文件,仅供参考

import Vue from "vue";
declare module "vue/types/vue" {
interface Vue {
$message: any,
$confirm: any
}
}

vue自定义插件封装,实现简易的elementUi的Message和MessageBox的更多相关文章

  1. Vue自定义插件方法大全

    新年第一天首先祝大家新年快乐,心想事成! 1.利用根实例构造函数的原型 //在构造函数的原型链上添加自定义属性 Vue.prototype.test = 'pomelo' //在其他组件中调用 con ...

  2. vue自定义插件

    1.新建js文件 utils.js,自定义方法 let local = { say() { console.log('我是插件里面自定义的方法') } } export default { insta ...

  3. vue自定义插件-弹框

    <template> <transition name="msgbox"> <div v-if="show" class=&quo ...

  4. 浅析vue封装自定义插件

    在使用vue的过程中,经常会用到Vue.use,但是大部分对它一知半解,不了解在调用的时候具体做了什么,因此,本文简要概述下在vue中,如何封装自定义插件. 在开始之前,先补充一句,其实利用vue封装 ...

  5. vue2.0 如何自定义组件(vue组件的封装)

    一.前言 之前的博客聊过 vue2.0和react的技术选型:聊过vue的axios封装和vuex使用.今天简单聊聊 vue 组件的封装. vue 的ui框架现在是很多的,但是鉴于移动设备的复杂性,兼 ...

  6. webpack + vue 项目 自定义 插件 解决 前端 JS 版本 更新 问题

    Webpack 是一个前端资源加载/打包工具.它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源. 它的异步加载原理是,事先将编译好后的静态文件,通过js对象映射,硬编 ...

  7. vue各种插件汇总

    https://blog.csdn.net/wh8_2011/article/details/80497620(copy) Vue是什么? Vue.js(读音 /vjuː/, 类似于 view) 是一 ...

  8. vue 常用插件,保存

    UI组件 element- 饿了么出品的Vue2的web UI工具套件 Vux- 基于Vue和WeUI的组件库 mint-ui- Vue 2的移动UI元素 iview- 基于 Vuejs 的开源 UI ...

  9. vue_简介_渐进式 js 框架_内置指令_自定义指令_自定义插件

    vue 尤雨溪 华裔 Google 工程师 遵循 MVVM 模式 编码简洁,体积小,运行效率高,适合 移动 / PC 端 开发 动态构建用户界面: 异步获取后台数据,展现到页面 渐进式 js 框架 渐 ...

随机推荐

  1. docthis & VS code

    docthis & VS code JSDoc 3 http://usejsdoc.org/ http://usejsdoc.org/about-getting-started.html ht ...

  2. Vue Learning Paths

    Vue Learning Paths Vue Expert refs https://vueschool.io/articles/vuejs-tutorials/exciting-new-featur ...

  3. BGV等 DeFi产品暴涨背后隐藏着什么?

    比特币突破两万七千美金,在此创造了历史.在比特币一路飙升的背后,到底是谁注入了"强心针".笔者认为今年以来推动BTC长期上涨的主要动力主要包括四个:经济形势恶化.央行大量放水(主要 ...

  4. 磁盘使用率/文件大小查看指南du & df

    一.前言 磁盘使用率,文件大小查看是我们日常使用命令.这两个是配合使用的,磁盘使用率过高告警了,那么得找到对应的磁盘(df),然后找到对应磁盘下的哪个目录和文件占用了空间(du). df(Disk f ...

  5. django学习-17.如何提供一个规范的接口返回值

    目录结构 1.前言 2.进行实际的一个完整流程操作 2.1.第一步:编写一个用于查询用户数据的视图函数 2.2.第二步:编写对应的一个url匹配规则 2.3.第三步:启动django项目[hellow ...

  6. 2.go语言入门----变量类型、声明变量、数组、切片

    基本变量类型 介绍几种基本的变量类型:字符串.int.float.bool package main import ( "fmt" ) // 列举几种非常基本的数据类型 func ...

  7. 【转载】Win10彻底格式化磁盘防止数据恢复的技巧

    转载地址 注意 要尽量删除数据,请在运行cipher /w时关闭其他所有应用程序. 1.如果你在格式化磁盘后想要防止数据被恢复, Format 命令,而现在只需在其后添加 /P 参数,即可用随机数据覆 ...

  8. 【资源下载】安卓VS鸿蒙第三方件切换宝典 V1.0

    下载<安卓VS鸿蒙第三方件切换宝典> 由于字数较多,本文仅展示部分,查看完整版请点击上方下载 众所周知,安卓应用开发经过这么多年的发展相对成熟和稳定,鸿蒙OS作为后来者兼容一个成熟的开发体 ...

  9. 数组的常用方法之split

    今天我们来聊一下数组的常用方法:split 返回值:一个新数组. 1.该方法可以直接调用不传任何值,则会直接将字符串转化成数组. var str = 'I love Javascript'; cons ...

  10. 如何在 C# 中使用 const,readonly,static

    平时在开发时经常会用到 const,readonly,static 关键字,可以肯定这些关键词是完全不同的概念,但有时候他们在用法上很相似以至于在场景中不知道选择哪一个,这篇文章我们就来讨论 C# 中 ...