开发vue插件的官方文档是这样描述的:
插件通常会为Vue添加全局功能。插件的范围没有限制,一般有下面几种:
1,添加全局方法或者属性,如: vue-element ,
2,添加全局资源:指令/过滤器/过渡等,如 vue-touch
3,通过全局 mixin方法添加一些组件选项,如: vuex,
4,添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
5,一个库,提供自己的 API,同时提供上面提到的一个或多个功能,如 vue-router
Vue.js 的插件应当有一个公开方法 install 。这个方法的第一个参数是 Vue 构造器 , 第二个参数是一个可选的选项对象:
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或属性
Vue.myGlobalMethod = function () {
// 逻辑...
}
// 2. 添加全局资源
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 逻辑...
}
...
})
// 3. 注入组件
Vue.mixin({
created: function () {
// 逻辑...
}
...
})
// 4. 添加实例方法
Vue.prototype.$myMethod = function (options) {
// 逻辑...
}
}
使用:
通过全局方法 Vue.use() 使用插件:
// 调用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)
也可以传入一个选项对象(定制一些自己的效果):
Vue.use(MyPlugin, { someOption: true })
看完文档可以动手自己试一试了,先给自己定需求:开发一个分页插件,可以定制显示分页按钮的最大个数和每页展示内容列表个数,在页面中定义一个含有Id的元素作为分页组件的包裹容器,分页组件可以自动渲染为其子元素在页面中渲染出来。此外我们想要在vue-cli架子下的任何一个vue组件中都能够this.$myMethod('id名',回调函数,{配置对象})的方式创建。
好了,按照上边的需求,我们结合文档应该选择‘添加实例方法’的方式开发我的组件。首先捋一捋思路,第一,要先建个index.js这里边应该含有我们插件的注册函数;第二,做一个分页vue组件,模板,样式,一些逻辑方法都写在这里边;第三,设置一个中间层,管理数据和方法。
看起来我的插件目录应该是这样的:
来看看index.js
import chooseP from './choosePages.vue' //引入组件
import {peacemaker} from './delivery' //引入中间层
var ChoosePages = {}; //定义一个对象
ChoosePages.install = function (Vue,options) {
//添加实例方法
// id 页面元素id名 字符串类型
// cb 回调函数 获取当前页码
// op 配置对象
Vue.prototype.$choosePages = (id,cb,op) => {
for(let property in op){
peacemaker.data[property] = op[property];
}
let choosePages = Vue.extend(chooseP);
let tpl = new choosePages().$mount().$el;
document.getElementById(id).appendChild(tpl);
peacemaker.doThings = cb;
}
}
export default ChoosePages;; //将对象暴露出去
中间层 delivery.js
export const peacemaker = {
data : {
//展示内容的列表总个数
listsNum:0,
//每页展示的内容列表个数
itemsNum:5,
//最多在页面上显示的按钮个数
btnNum :16
},
doThings : null //回调函数
}
分页组件 choosePage.vue
<template>
<div class="choosePages">
<a href="javascript:;" class="firstPage" @click="toFirst">首页</a><a
href="javascript:;" class="last" @click="chooseBtnLast"><i></i></a><a
href="javascript:;"v-for="item in showBtns" :class="{pageNum : chooseBtnIndex === item }" @click="clickBtn(item)">{{item}}</a><a
href="javascript:;" class="next" @click="chooseBtnNext"><i></i></a><a
href="javascript:;" class="lastPage" @click="toLast">尾页</a><span
class="hint" v-if="isShowRight">跳转到</span><input type="text" v-model="pageIndex" @keyup="goIndex" v-if="isShowRight"><span
v-if="isShowRight">页</span><span v-if="isShowRight">共{{btns.length}}页</span>
</div>
</template>
<script>
import {peacemaker} from './delivery'
export default {
data(){
return {
btns : [],
showBtns : [],
chooseBtnIndex :1, //页码
overNum:0,
pageIndex:'1',
}
},
created() {
this.createBtns(this.listsNum);
},
computed: {
//数据列表总个数
listsNum:function () {
return peacemaker.data.listsNum
},
//每页展示的内容列表个数
itemsNum:function () {
return peacemaker.data.itemsNum
},
//页面最多展示的个数
lengthBtns: function () {
return peacemaker.data.btnNum
},
//按钮数大于限定展示时,显示跳转页面选框
isShowRight:function () {
return this.btns.length > this.lengthBtns ? true : false;
}
},
methods: {
//跳转页面
goIndex(e){
if(e.keyCode !== 13 || +this.pageIndex > this.btns.length){
return;
}
this.chooseBtnIndex = +this.pageIndex;
this.getPageMessage ();
if(+this.pageIndex > this.lengthBtns){ //选择的页面大于显示个数限制
this.overNum = +this.pageIndex - this.lengthBtns;
this.showBtns = null;
this.showBtns = this.btns.slice(this.overNum,this.lengthBtns+this.overNum);
}else{
this.overNum=0;
this.showBtns = null;
this.showBtns = this.btns.slice(this.overNum,this.lengthBtns+this.overNum);
}
},
//5个列表为一页(默认可配置)
createBtns(n){
let length = 0;
if(n>this.itemsNum){
length = parseInt(n/this.itemsNum);
if(parseInt(n%this.itemsNum)>0){
length = length + 1;
}
for(let i=0;i<length;i++){
this.btns.push(i+1);
}
if(this.btns.length>this.lengthBtns){ //按钮长度不能大于长度设定值
this.showBtns = null;
this.showBtns = this.btns.slice(0,this.lengthBtns);
}else{
this.showBtns = null;
this.showBtns = this.btns;
}
}else {
return;
}
},
getPageMessage (){
//请求选择的页面信息
console.log( '请求的第页:'+this.chooseBtnIndex);
//通过回调函数把页码数传递出去
peacemaker.doThings(this.chooseBtnIndex);
},
clickBtn(index){
this.chooseBtnIndex = index;
this.getPageMessage ();
},
chooseBtnLast(){ //前一个按钮
if(this.chooseBtnIndex === 1){
return
}
this.chooseBtnIndex--;
this.getPageMessage ();
if(this.overNum>0){ //按钮长度不能大于长度设定值
this.overNum--;
if(this.overNum < 0){
return
}
this.showBtns = null;
this.showBtns = this.btns.slice(this.overNum,this.lengthBtns+this.overNum);
}
},
chooseBtnNext(){ //后一个按钮 向后移动
if(this.chooseBtnIndex === this.btns.length){
return
}
this.chooseBtnIndex++;
this.getPageMessage ();
if(this.chooseBtnIndex>this.lengthBtns){ //按钮长度不能大于长度设定值
this.overNum++;
this.showBtns = null;
this.showBtns = this.btns.slice(this.overNum,this.lengthBtns+this.overNum);
}
},
toFirst(){
if(this.chooseBtnIndex === 1){
return
}
this.chooseBtnIndex=1;
this.getPageMessage ();
if(this.overNum>0){ //按钮长度不能大于长度设定值
this.overNum=0;
this.showBtns = null;
this.showBtns = this.btns.slice(this.overNum,this.lengthBtns+this.overNum);
}
},
toLast(){
if(this.chooseBtnIndex === this.btns.length){
return
}
this.chooseBtnIndex=this.btns.length;
this.getPageMessage ();
if(this.btns.length>this.lengthBtns){ //按钮长度不能大于长度设定值
this.overNum = this.btns.length - this.lengthBtns;
this.showBtns = null;
this.showBtns = this.btns.slice(this.overNum,this.lengthBtns+this.overNum);
}
}
},
}
</script>
<style scoped lang="css">
.choosePages{
text-align: center;
margin: 34px 0;
}
.choosePages a{
display: inline-block;
width: 32px;
height: 32px;
line-height: 32px;
text-align: center;
box-sizing: border-box;
border: 1px solid #999;
margin-right: 10px;
color:#333;
background: #fff;
font-size: 13px;
}
.choosePages a i{
display: inline-block;
width: 10px;
height: 12px;
}
.choosePages .last i{
background: url("./icon/icon_last@2x.png") no-repeat 0 0;
background-size: 10px 12px;
}
.choosePages .last:hover{
background: rgba(200,200,200,.2);
}
.choosePages .next i{
background: url("./icon/icon_next@2x.png") no-repeat 0 0;
background-size: 10px 12px;
}
.choosePages .next:hover{
background: rgba(200,200,200,.2);
}
.choosePages .pageNum{
background: #000;
border: 1px solid #000;
color: #fff;
}
.choosePages .firstPage,.choosePages .lastPage{
width: 45px;
}
.choosePages .firstPage:hover,.choosePages .lastPage:hover{
background: #f2f2f2;
border: 1px solid #666;
}
.choosePages .lastPage{
margin-right: 0;
}
.choosePages span{
color:#333;
font-size: 13px;
margin-left: 5px;
margin-right: 5px;
}
.choosePages .hint{
margin-left: 15px;
}
.choosePages input{
width: 26px;
text-align: center;
}
</style>
然后就是如何用了,在入口js文件中(app.js)
import ChoosePages from '../../plugin/choosePage/index' //引入插件文件
Vue.use(ChoosePages); //使用插件
最后在需要应用的组件中就可以应用了
this.$choosePages('pagesBtn',function(index){
console.log(index,'我在应用页面');
},
{
listsNum:10, // 列表数据总个数(必填)
itemsNum:5, // 每页要显示的列表数(默认5,选填)
btnNum :4 // 页面限定显示的按钮个数(默认16,选填)
})
ps:以上就是vue插件一个简单的小开发,由于本人的能力所限,难免会出现纰漏和错误,欢迎留言斧正!
这里提供一个demo地址: