vue插件開發實踐與要點

其實就跟組件差很少意思,組件也能夠實現相關的效果,但要在用到的地方都引用
插件就能夠全局註冊,不需引用html

試着擼一個插件,有2個功能,提示和對話框vue

網上找了個toast插件的代碼,改了改,擴展加了個dialog,增長了註釋app

插件文件結構less

 

在入口文件中註冊:dom

/* 自定義插件 */
import {Message,vDialog} from './components/vtoast/index'
Vue.use(Message).use(vDialog)

 

調用方式ide

    methods:{
        showtoast(){
            this.$vtoast({
                duration:1100,
                message:'哈哈哈'
            });
        },
        showdialog(){
            let that  = this
            this.$vdialog.alert({
                isShow: true,
                //插件默認值title爲空,若是這裏不放title,則不會顯示title的dom
                title:'你好',
                message:'哈哈哈',
            })
            .then(()=>{
                that.test = '修改了'
            })
        }
    },

toast.vue:函數

<template>
    <transition name="fade">
    <div class="v-msg" v-show="isShow">
        <span>{{message}}</span>
    </div>
    </transition>
</template>

<script>
export default {
    
    data(){
        return {
            message: '默認提示',
            isShow : false
        }
    },
    methods:{
        close(){
            this.isShow = false
        },
        show(){
            this.isShow = true
        }
    }
}
</script>

<style>
.v-msg{
    color:#fff;display: inline-block;background-color:rgba(0,0,0,0.8);padding:10px;
    border-radius: 4px;
    position: fixed;left:50%;bottom:10px;transform: translateX(-50%)
}
.fade-enter-active, .fade-leave-active { transition: all .2s; }
.fade-enter, .fade-leave-to { opacity: 0; }
</style>

dialog.vue:flex

<template>
    <transition name="fade">
    <div v-show="isShow">
        <div class="dialog_mask" v-show="mask" @click="close"></div>
        <div class="dialog">
            <div class="title" v-show="title">{{title}}</div>
            <div class="message">{{message}}</div>
            <div class="btgroup">
                <button class="button" @click="close" v-if="cancle">取消</button>
                <button class="button sure" @click="cb();close()">肯定</button>
            </div>
        </div>
    </div>
    </transition>
</template>

<script>
export default {
    props:{
        
    },
    data(){
        return {
            title:'',
            message:'默認內容消息',
            isShow : false,
            mask:true,
            cancle:false
        }
    },
    methods:{
        close(){
            this.isShow = false;
        }
    }
}
</script>

<style lang="less" scoped>

.dialog_mask{
    position: fixed;top:0;right:0;bottom: 0;left: 0;background-color:rgba(0,0,0,0.8);
    z-index: 100000;
}
.dialog{
    min-width:90vw;max-width:90vw;color:#333;display: inline-block;background-color: #fff;overflow: hidden;
    position: fixed;left:50%;top:50%;transform: translate(-50%,-50%);z-index:100001;border-radius:5px;
    .title{
        font-size:16px;padding:20px 0px 0px;text-align: center;
    }
    .message{
        color:#999;font-size:16px;padding:25px;
    }
    .btgroup{
        display:flex;align-items: center;justify-content: space-between;border-top:1px solid #eee;
    }
    .button{
        font-size:16px;flex:1;padding:14px 0px;border:none;background-color: #fff;
        &.sure{color:#293}
        &:active{background-color: #eee;}
        &:nth-child(2){border-left:1px solid #eee;}
    }
}
.fade-enter-active, .fade-leave-active { transition: all .2s; }
.fade-enter, .fade-leave-to { opacity: 0; }

</style>

index.jsui

//插件的install會放入vue.use方法中運行,本文件中不用import vue

// TOAST插件
import mytoast from './toast.vue'
const Message = {}
Message.install = function (Vue, options) {
    //返回一個vue實例構造器
    const VUECONSTRUCTOR = Vue.extend(mytoast)
    let _VUEINSTANCE 
    const initInstance = () => {
        //實例化vue示例 下面能夠直接調用methods裏面的方法
        _VUEINSTANCE = new VUECONSTRUCTOR()
        // 取得通過vue裏面折騰以後生成的html
        let El = _VUEINSTANCE.$mount().$el    
        //掛載到body中
        document.body.appendChild(El) 
    }
    Vue.prototype.$vtoast = (options)=>{
            //單例模式,防止重複掛載html
            if (!_VUEINSTANCE) {
                initInstance()//建立實例
            }
            //將調用的參數對象傳給_VUEINSTANCE對象,覆蓋組件內的初始配置
            // 官方:https://cn.vuejs.org/v2/guide/list.html#對象更改檢測注意事項
            Object.assign(_VUEINSTANCE, options) 

            //調用插件裏的顯示方式
            _VUEINSTANCE.show()
            // 注意,若是是自動消失的toast 每閃調用(顯示),都要再次聊友
            // 不要使用實例裏面的方法,由於插件只掛載一次,dom便存於html中
            // 因此,這裏的vue插件實例生命週期只生效一次(created,mounted)
            setTimeout(() => {
                _VUEINSTANCE.close()
            }, options.duration)
    }
}

// DIALOG插件
import myDialog from './dialog.vue'
const vDialog = {}
vDialog.install = function (Vue, options) {
    const VUECONSTRUCTOR = Vue.extend(myDialog)
    let _VUEINSTANCE 
    const initInstance = () => {
        _VUEINSTANCE = new VUECONSTRUCTOR()
        let El = _VUEINSTANCE.$mount().$el
        document.body.appendChild(El)
    }
    //這裏最好用對象封裝方法的模式,調用時代碼好閱讀一些
    Vue.prototype.$vdialog = {
        alert(options) {
            if (!_VUEINSTANCE) {
                initInstance()
            }
            //默認顯示顯示肯定按鈕,因此回調給一個默認空函數
            Object.assign(_VUEINSTANCE, options,{cb:()=>{}})
            //以便連續調用
            return this
        },
        then(options){
            //若是不調用then只顯示肯定按鈕
            //這裏的回調函數名cb,必需和插件裏面所調用的同樣
            Object.assign(_VUEINSTANCE, {cancle:true,cb:options})
        }
    }
}

export {Message,vDialog}

 

總結相關要點:this

  • 綁定多個事件使用  @click="cb();close()"
  • Object.assign(_VUEINSTANCE, options) ,把調用時的參數(包括值,方法)合併進基於vue構造器建立的插件實例中vue會自動把參數放到對應的地方,數據放data,方法放methods,但本實踐沒有把回調方法也放進同一個參數中而是爲了代碼清晰,另起一個連續調用的方法來處理
相關文章
相關標籤/搜索