美文网首页
基于Promise将Vue组件封装为插件

基于Promise将Vue组件封装为插件

作者: 一蓑烟雨任平生_cui | 来源:发表于2018-08-17 11:26 被阅读0次

    项目中有些组件在很多场景下都会用到,比如toast、messageBox、alert等,如果作为组件使用,则每个用到的地方都需要引入、注册等操作;如果把组件封装成插件,并作为实例的公共方法,则在整个应用中即可随处调用。

    以messageBox为例,封装插件。

    步骤如下:

    1. 编写组件
    2. 调用Vue.extend()方法,创建构造器
    3. 创建组件实例
    4. 挂载并插入文档
    5. 往构造器上添加回调,监听用户的操作,取消还是确定
    6. 创建Promise的实例
    7. 添加方法到Vue的原型和实例上
    8. 监听浏览器的前进、后退事件,当离开页面的时候,隐藏组件

    具体如下:

    1. 首先编写组件:
    <template>
        <div v-show="show">
        <!-- ui-mask为自己封装的组件 -->
            <ui-mask :showMask="show" :opacity="0.2"></ui-mask>
            <div class="message-box">
                <h1 class="message-title" v-show="title">{{title}}</h1>
                <p class="content">{{content}}</p>
                <div class="message-button">
                    <p class="fl" @click="cancleMessage" v-show="cancle">{{cancle}}</p>
                    <p class="fr" @click="sureMessage">{{sure}}</p>
                </div>
            </div>
        </div>
    </template>
    
    1. 样式使用scss

    样式省略...

    1. js部分代码
    data() {
        return {
            show: false,
            title: '',
            content: '',
            sure: '确定',
            cancle: ''
        }
    },
    methods: {
        sureMessage() {
            this.show = false;
            this.callback && this.callback('confirm');
        },
        cancleMessage() {
            this.show = false;
            this.callback && this.callback();
        }
    }
    

    封装插件

    • 如果插件是一个对象,则必须提供install方法,Vue.use的时候调用install方法
    • 如果插件是函数,函数将作为install方法执行。

    index.js

    import messageBox from './messageBox.vue';
    
    export default {
        install(Vue, options = {}) {
            // 创建构造函数
            const MessageBox = Vue.extend(messageBox);
    
            let instance;
            let currentMsg;
    
            // 绑定window的history事件
            window.addEventListener('popstate', () => {
                if (instance) {
                    insatnce.show = false; 
                    instance = null;
                    currentMsg = null;
                }
            });
    
            let messageBoxFunc = (options = {}) => {
                if (!instance) {
                    // 创建实例
                    instance = new MessageBox({
                        // 需要挂在到某一个元素上
                        el: document.createElement('div')
                    });
    
                    // 如果没有传el,则需要调用实例的$mount方法,传入元素
                    // instance = new MessageBox().$mount(document.createElement('div'));
                  
                  // 如果没有传递el选项、$mount()方法也没有传递任何参数,则模板将被渲染为文档之外的元素,亦是可行的。
    
                    // 插入到DOM中
                    document.body.appendChild(instance.$el)
                }
    
                // 合并参数与实例
                Object.assign(instance, options);
    
                // 在构造器的原型上扩展一个回调,修改promise的状态
                MessageBox.prototype.callback = defaultCallback;
    
                return new Promise((resolve, reject) => {
                    // 保存两个回调,在action改变的时候执行
                    currentMsg = {
                        resolve,
                        reject
                    }
                })
            };
    
            function defaultCallback(action) {
                if (action === 'confirm') {
                    currentMsg.resolve('confirm');
                }
                currentMsg.reject('cancle');
            }
    
            // 将方法扩展到Vue的原型和实例上
            Vue.prototype.$messageBox = Vue.messageBox = messageBoxFunc;
        }
    }
    

    这样一个messageBox插件就封装好了,在应用的任何地方都可以调用。可以使用Promise的方式then、catch,亦可使用async/await的方式。

    Usage

    // 方式一 
    this.$messageBox()
    .then(res => {
    
    })
    .catch(err => {
    
    })
    
    // 方式二
    // 所在的方法一定是async函数
    try {
        await this.$messageBox();
    
        // do something
    }
    catch(e) {
        // do... 
    }
    

    总结:

    用到的知识点Promise、原型链、async/await。

    相关文章

      网友评论

          本文标题:基于Promise将Vue组件封装为插件

          本文链接:https://www.haomeiwen.com/subject/pyyzbftx.html