Vue自定义插件实现

  • Vue.use源码分析

插件是一个对象,必须包含install属性,且是个函数。因为使用插件时需要Vue.use(plugin),所定义的插件相当于use这个函数的一个参数。下面了解下Vue.use主要干了什么。先看看Vue.use得源码:

Vue.use = function (plugin) {
 /* istanbul ignore if */
  if (plugin.installed) {
    return
  }
  // additional parameters
  var args = toArray(arguments, 1);
  args.unshift(this);
  if (typeof plugin.install === 'function') {
    plugin.install.apply(plugin, args);
  } else if (typeof plugin === 'function') {
    plugin.apply(null, args);
  }
  plugin.installed = true;
  return this
};

每当插件install以后就会设置plugin.installed = true;,对应如果已经install了就回直接return,具体如下:

if (plugin.installed) {
  return
}

下面看看第一次执行,首先,使用use的目的就是要执行plugin中的install函数。我们在使用Vue.use的时候,第一个参数传的时plugin本身,后面传的才是需要的参数,所有就有了如下的toArray的参数构造。作用就是把类数组(参数:arguments),剔除第一个参数plugin本身后,转化为真正的数组。

function toArray (list, start) {
  start = start || 0;
  var i = list.length - start;
  var ret = new Array(i);
  while (i--) {
    ret[i] = list[i + start];
  }
  return ret
}

接下来就是:args.unshift(this);把this插入数组最前面(此处是Vue.use调用,所以this指向Vue),相当于[Vue, ...]。之后执行install函数,判断plugin.install是函数则执行plugin.installplugin本身是函数则执行plugin。最后设置plugin.installed = true;避免重复执行。

if (typeof plugin.install === 'function') {
  plugin.install.apply(plugin, args);
} else if (typeof plugin === 'function') {
  plugin.apply(null, args);
}
plugin.installed = true;
  • 全局组件自动注册Vue.component()

首先新建一个文件夹,里面存放需要全局注册的组件,我实在src下面新建了components,下面展示一个弹窗的样例,组件内的name属性必须加上,为后面全局注册的组件名称准备。这里我用的是name: 'AddModal'

<template>
    <div id="add_modal" :style="visible ? '' : 'display: none;'">
        <transition name="drop">
            <div class="add_modal">
                <h2 v-text="title"></h2>
                <div class="add_content">
                    <slot name="content"></slot>
                </div>
                <div class="add_foot">
                    <slot name="foot"></slot>
                </div>
            </div>
        </transition>
    </div>
</template>
<script>
export default {
    name: 'AddModal',
    props: ['visible', 'title']
}
</script>
<style scoped lang="less">
    #add_modal{
       display: flex;
       position: fixed;
       top: 0;
       right: 0;
       bottom: 0;
       left: 0;
       background-color: rgba(43, 60, 77, 0.9);
       z-index: 999; 
       .add_modal {
            position: relative;
            top: 0;
            margin: auto;
            height: auto;
            width: 600px;
            min-height: 440px;
            padding: 20px;
            text-align: center;
            background-color: #fff;
            h2{
                font-size: 28px;
            }
            .add_content{
                width: 100%;
                min-height: 320px;
                padding-bottom: 15px;
            }

            .add_foot{
                width: 100%;
                height: 50px;
                display: flex;
                justify-content: flex-end;
            }
        }
    }
</style>

接下来定义一个plugin.js,通过require.context()获取需要注册的公用组件数组集合,require.context('../components', true, /.vue$/).keys()获取一个以vue结尾的文件路径的数组集合。然后通过require()得到具体的组件信息,如下:

//require.context(遍历的路径, 是否遍历子目录, 正则匹配)
let components = require.context('../components', true, /.vue$/).keys().map(key => {
    return require(`../components${key.replace('.', '')}`).default
})

接下来在install中将遍历获取的组件全局注册一下

export default {
    install: (Vue) => {
        components.forEach(component => {
            Vue.component(component.name, component);
        });
    }
}
  • 常用方法全局混入Vue.mixin()
export default {
    install: (Vue) => {
        Vue.mixin({
            methods: {
                /**
                 * 十三位时间戳
                 * @param {timestamp} 
                 */
                timestampToTime(timestamp) {
                    let date = new Date(timestamp);
                    let Y = date.getFullYear() + '-';
                    let M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-';
                    let D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
                    let h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
                    let m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) + ':';
                    let s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
                    return Y + M + D + h + m + s;
                },
            }
        })
    }
}
  • Vue全局指定创建Vue.directive()
import { Message } from 'iview';//iview组件提示
export default {
    install: (Vue) => {
        /**
         * 输入框限制输入长度
         * 使用 v-limitation="参数:输入限制长度"
         */
        Vue.directive('limitation', {
            inserted: function(el, binding){
                const input = el.getElementsByClassName('ivu-input')[0];
                input.onblur = function(){
                    if(input.value.length > binding.value){
                        input.value = input.value.slice(0, binding.value);
                        Message.warning(`不可超过${binding.value}位`);
                    }
                };
            }
        });
    }
}
  • 插件使用

首先在main.js引入插件,然后通过Vue.use就ok~

import lplugin from './plugins/l-plugin';
Vue.use(lplugin);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值