前言

本想把本篇取名:从0开始写前端UI框架:实现你人生中的第一个jQuery插件 ,但感觉标题太长,所以简单明了直接取后面主题为题目吧。

前一篇文章 已经对my-ui框架做了简单的介绍。谈到了我是如何想起做这个框架的,并描绘了这个框架的大致功能或者说是组件,文章最后举了个已经实现的table表格功能为例子,万里长征就从这里开始!接下来咱们就来剖析如何实现这一简单的功能了,我已经实现了一个table组件功能,也叫做插件,那么接下来你就要开始来了解什么是插件,以及如何写一个插件了。

预备知识

科普插件知识:插件(Plug-in,又称addin、add-in、addon或add-on,又译外挂)是一种遵循一定规范的应用程序接口编写出来的程序。其只能运行在程序规定的系统平台下(可能同时支持多个平台),而不能脱离指定的平台单独运行。因为插件需要调用原纯净系统提供的函数库或者数据。

简而言之,插件就是现有框架的补丁或扩展,jQuery的插件必须要依赖于jQuery库。学习插件开发之前,你最好具备以下知识:

  1. JavaScript面向对象思想,把这种脚本语言当成面向对象来看待。重点是提升你的JavaScript封装能力。你可以尝试封装一个带有四则运算能力的计算器对象,或者封装一个可以自由切换选项卡的对象,或者一个抽奖功能等。这里的重点是练习你的封装能力,而不是算法。
  2. 理解JavaScript中this的功能,当this处于js文件裸体内,当this处于函数内,当this处于对象内分别指向的是谁。
  3. 理解JavaScript中的原型以及原型链,搞明白对象属性和原型属性有什么区别,并且弄明白prototype关键字的用意。
  4. JavaScript闭包和模块化编程,尤其是JavaScript为了避免变量污染如何做到隐藏对象作用域的。

嗯,上述几点我建议你在网上找找相关课程看看,或者翻阅专栏博客看看,当然了,实在找不到那翻阅我的CSDN博客看也行,不过我写的系列文章理解不深,只能作为入门级别的理解。

编写你人生的第一个jQuery插件

下面假设你已经具备上面我提到的前端编程技能了,那么接下来我们就来了解jQuery插件编程了。通过查阅jQuery帮助文档我们可以知道jQuery的插件是这样写的:

$.fn.jquery //.jquery 属性是通过 jQuery 原型赋值的,通过使用它的别名 $.fn 进行引用。

上诉语法将属性注册到jQuery对象原型上,这里多说一句的是:jQuery本身是一个对象,属于一个大的Ojbect。现在我想在这个大型的Object上面实现自己的方法,例子如下:

$.fn.extend({   "bold": function () {// 加粗字体return this.css({ fontWeight: "bold" });}
});

这时候jQuery对象就具备了一个叫做bold的属性,这个属性是一个函数。这时候jQuery的原有功能不变,额外多出了bold()函数,这个函数只实现一个功能:字体加粗。别着急运行上述代码,一般来说为了避免变量污染,我们会将上述代码放在一个匿名函数里面:

(function ($) {$.fn.extend({"bold": function () {/// 加粗字体return this.css({ fontWeight: "bold" });}});})(jQuery);

上述代码体现了JavaScript的闭包,首先定义了一个匿名函数,并且使用(jQuery)立刻调用它,并且传递进去jQuery对象,也就是那个$对象,匿名函数的内容我就不赘述了。接下来咱就可以调用这个咱基于jQuery扩展出来的方法了。

$(function() {$('#div').bold();
});

上述语法你应该很熟悉,就是jQuery的标准调用语法,只不过此刻jQuery多了个bold()函数功能摆了。

亲自试一试上述例子哦!

怎么样?你人生的第一个jQuery插件就这样开发出来了,这个功能虽然很简单,它利用jQuery原有的选择器语法选择出你想要的元素,然后再链式调用,将之前选中的元素传递给你的bold()函数。至于这个函数实现怎么样的内容,那是你说了算哦,这里想要注意的是你必须注意那个this指的是谁。

实现my-ui的table组件

既然你已经开发出了人生的第一款jQuery插件了,那么我们继续吧。

框架区别

有人说,框架分3种:

  1. 第一种是工具集toolkit。就是平时开发中经常用到的代码段封装成,比如处理字符串的代码段,比如处理日期的函数,众多工具集合在一起就是一个toolkit了。
  2. 第二种是Libaray。在Vue,React以及Angluar出来之前,我们也称它们为框架,比如jQuery,BootStrap,以前我们一直以为它是一个框架,但是现在你去看它的官网,官方给它的定义是库。
  3. 第三种是Framework,比较典型就是MVVM框架,人们认为这才是真正意义上的框架。

有图有真相,jQuery官网对jQuery的定义:
Bootstrap对它自己的定义:

这一种好理解,就是工具集,关于第二种和第三种,有人总结区别如下:

库是将代码集合成的一个产品,供程序员调用。面向对象的代码组织形式而成的库也叫类库。面向过程的代码组织形式而成的库也叫函数库。

在函数库中的可直接使用的函数叫库函数。开发者在使用库的时候,只需要使用库的一部分类或函数,然后继续实现自己的功能。

框架则是为解决一个(一类)问题而开发的产品,框架用户一般只需要使用框架提供的类或函数,即可实现全部功能。可以说,框架是库的升级版。开发者在使用框架的时候,必须使用这个框架的全部代码。

框架和库的比较可以想像为:
假如我们要买一台电脑。框架为我们提供了已经装好的电脑,我们只要买回来就能用,但你必须把整个电脑买回来。这样用户自然轻松许多,但会导致
很多人用一样的电脑,或你想自定义某个部件将需要修改这个框架。而库就如自己组装的电脑。库为我们提供了很多部件,我们需要自己组装,如果某个部件
库未提供,我们也可以自己做。库的使用非常灵活,但没有框架方便。

api设计

上述已经讲述了框架之前的区别,我们要实现的框架属于是第二种:Libaray

我对my-ui的定位是:基于jQuery扩展实现的前端UI框架,封装统一API调用风格,汇聚众家优秀框架以及插件之所长,借鉴了easyui api设计风格,bootsrap的样式,追求视角完美的前端框架。

那么接下来第一步就是来设计api了,虽然我还未具备设计整个框架的能力,但是仿造easyui先设计table组件是没问题的。下面是我借鉴的easyui的api,如下:

table属性
属性名 数据类型 备注 默认值
url 字符串 table表格请求后台的url地址 null,必填
method 字符串 http请求方式,支持5种请求方式[get, post, put, delete, head] get,选填
函数名 函数 向组件种注册函数,一般在formatter属性中指定到该函数名,否则不会被调用 null,选填
列属性
属性名 数据类型 备注 默认值
field 字符串 从后台请求到的数据列表元素的属性名 null,必填
formatter 字符串 数据格式化形式,框架提供了[number, date-box]类型,需要额外定义格式逻辑可指定回调函数名,调用回调函数时传递的参数列表分别是:value, row, index null,选填

开启你的编程之旅

看到这里,人生好像就有个小目标要去实现了,你要完成的工作是在jQuery对象上再添加原型对象和属性,来处理一个table表格,这个原型对象能接收url,medhod以及函数等参数,并且能去扫描页面中表格每一列的属性,生成一个table表格。接下来咱要编程实现这个功能。

假设抛开什么jQuery原型对象,什么抽象,封装,什么闭包,就是用jQuery来实现一个简单的表格,你是如何做的?我思考许久之后,我是这么做的。

1.定义table用到的css样式:

/**
* myui-table表格定义样式
*/
@charset "UTF-8";caption {caption-side: top;text-align:left;padding: .5em;color: black;font-weight: bold;font-size: 15px;
}
.myui-table {width: 99%;border-collapse: collapse;margin: 3px;font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
}.myui-table td, .myui-table th {font-size: 1em;border: 2px solid rgba(255, 255, 255, 1);padding: 3px 3px 2px 3px;text-align: center;
}.myui-table th {height: 45px;font-size: 1.1em;padding-top: 5px;padding-bottom: 4px;background-color: #4fa6db;color: #ffffff;
}.myui-table tbody tr:nth-child(even) td {background-color:#f9f9f9;height: 28px;
}.myui-table tbody tr:nth-child(odd) td {background-color:#eeeeee;height: 28px;
}

2.在html页面中定义table元素

<table id="table" class="myui-table"><caption>梁山好汉排名</caption><tbody><tr><th style="height: 5px;" field="index">座次</th><th style="height: 5px;" field="name">原名</th><th style="height: 5px;" field="nickName">昵称</th><th style="height: 5px;" field="constellation">星宿</th><th style="height: 5px;" field="birthDay" formatter="daily-date">生日</th><th style="height: 5px;" field="sex" formatter="sexFormatter">性别</th><th style="height: 5px;" field="effectiveness" formatter="number">战斗指数</th><th style="height: 5px;" field="specialSkills">特殊技能</th><th style="height: 5px;" field="remark">备注</th></tr><tr><td>1</td><td>宋江</td><td>呼保义</td><td>天魁星</td><td>1995-01-01</td><td>男</td><td>4.12</td><td>忠义双全</td><td>梁山好汉大BOOS</td></tr><tr><td>2</td><td>卢俊义</td><td>玉麒麟</td><td>天罡星</td><td>1996-02-01</td><td>男</td><td>4.32</td><td>替天行道</td><td>梁山No.2人物</td></tr><tr><td>3</td><td>吴用</td><td>星智多星</td><td>天机星</td><td>2000-01-01</td><td>男</td><td>5.00</td><td>锦囊妙计</td><td>我军及友军精神力上升</td></tr><tr><td>4</td><td>公孙胜</td><td>入云龙</td><td>天闲星</td><td>2001-01-01</td><td>男</td><td>4.31</td><td>五雷天罡正版法</td><td>区域内敌人禁咒</td></tr><tr><td>5</td><td>孙二娘</td><td>母夜叉</td><td>地壮星</td><td>1999-01-01</td><td>女</td><td>2.56</td><td>未知</td><td>地壮星母夜叉孙二娘</td></tr><tr><td>6</td><td>景住</td><td>金毛犬</td><td>地狗星</td><td>1996-01-01</td><td>女</td><td>2.12</td><td>判官笔</td><td>梁山好汉第108位好汉</td></tr></tbody></table>

这样子你的页面展示如下:

函数级别的封装

上面已经页面效果渲染出来了,接下来你应该很快想到最简单级别,函数级别的封装了。你要将上诉代码封装在一个JavaScript函数里面,table body元素是动态生成出来的。那么接下来你的代码就变成这样子了:

html代码

        <table id="table" class="myui-table"><caption>梁山好汉排名</caption><tr><th style="height: 5px;" >座次</th><th style="height: 5px;" >原名</th><th style="height: 5px;" >昵称</th><th style="height: 5px;" >星宿</th><th style="height: 5px;" >生日</th><th style="height: 5px;" >性别</th><th style="height: 5px;" >战斗指数</th><th style="height: 5px;" >特殊技能</th><th style="height: 5px;" >备注</th></tr></table>

这时候你需要写一个JavaScript代码段处理这个表格如下:

            $.ajax({type: 'get',dataType: "json",url: 'xxx/xxx/xxx'success: function (data) {var table = $("#table");if (data.length > 0) {var html = "";for (var i = 0; i < data.length; i++) {html += "<tr>" +"<td>" + data[i].字段名1 + "</td>" +"<td>" + data[i].字段名2 + "</td>" +"<td>" + data[i].字段名3+ "</td>" +"<td>" + data[i].字段名4 + "</td>" +......"<td>" + data[i].字段名9 + "</td>" +"</tr>";}$(html).appendTo(table);}}});

如果你是有jQuery编程经验的开发者,你应该看到,这个代码段只做了两件事:

  1. ajax请求后台数据
  2. 拿到请求的数据循环遍历填充table表格

插件级别的封装

如果你感觉上诉代码没问题了,并且我相信你很轻松的看出我是怎么实现的,并且你实现的会更好。那么咱可以继续下去了,接下来就是插件级别的封装。

回顾本篇开头第2小节提到的jQuery插件开发,咱得把这段代码逻辑注册到jQuery对象原型上去。封装的代码如下:

(function($) {//定义全局变量var url = "";var method = "GET";// plugin definition$.fn.table = function(options) {url = options.url ||'';method = options.method || "GET";// $.ajax({url: url,method: method,success:function (response, index) {//上诉ajax响应体里面的代码}});};//  ...
})(jQuery);

此时调用该插件的代码改为

 $('#table').table({url : './table_data.json',});

如果你已经具JavaScript对象知识,不难看到,我的table组件传过去一个字面量Object对象,对象就一个属性:url,属性值.是一个json串的url地址。而插件的构造函数中有一个options变量,可以接收Object对象,这样的好处就是参数传递很容易扩展。

api完整实现

Ok,到此可以完全来实现设计的api需求了,那个api设计中大概要求我们:

  1. 能动态接收请求数据地址url参数,必选
  2. http请求方式,可选,默认值为get
  3. 请求到的数据,可以每一列filed属性属性值填充数据
  4. 数据可能需要格式化,比如返回一个金额123.456,用户可能只需要展示12.34。比如返回性别可能是true/alse,但是展示的时候是男/女等

完整的代码如下

(function($) {// plugin definition$.fn.table = function(options) {//放弃全局变量定义的用法,避免一个页面引用两次插件数据冲突this.url = options.url ||'';this.method = options.method || "GET";this.dataOptions = [];this.datas = [];this.options = options || {};var _this = this;//遍历thread的所有tr,只取带有field的列var theads = $(this).find("tr");$(theads).each(function(index, trObject) {$(trObject).children().each(function(index, tdObject) {if(typeof($(tdObject).attr("field")) != "undefined") {var ojbect = {};ojbect.field = $(tdObject).attr("field");ojbect.formatter = $(tdObject).attr("formatter");_this.dataOptions.push(ojbect);}});});//请求数据$.ajax({url : this.url,method : this.method,success:function (response, index) {$.each(response, function(index, value) {_this.datas.push(value);});var table = _this[0];var html = getHtml(_this.datas, _this.dataOptions, _this.options);$(html).appendTo(table);}});};// 计算table的html元素function getHtml(datas, dataOptions, options) {var html = "";//双重for循环变量属性和值$(datas).each(function(index, value){html += "<tr>";$(dataOptions).each(function (index1, value1) {if(value1.field === 'index') { //处理序号html += "<td>" + formatter(index+1, null) +"</td>";} else if(options.hasOwnProperty(value1.formatter) && typeof options[value1.formatter] === 'function') { //处理回调函数//调用回调函数,并返回值var result = options[value1.formatter].call(this, value[value1.field], value, index);html += "<td>" + result +"</td>";} else { //处理其他类型html += "<td>" + formatter(value[value1.field], value1.formatter) +"</td>";}});html += "</tr>";});return html;};//格式化数据function formatter(value, formt) {if(undefined != formt && value != null) {switch(formt) {case 'number':value = value.toFixed(2);break;case 'daily-date':'2020-01-01'break;default:value = value;}}return value;}//  ...
})(jQuery);

上诉代码已经完全实现了api的基本功能,此可你可以把代码段放到单独的js文件中去了,此时调用插件的代码变为:

$('#table').table({url : './table_data.json',sexFormatter : function (value, row, index) { //性别格式化回调函数if(value) {return "男";} else if(!value) {return "女";}return value;}});

到此,我人生的第一款jQuery插件已经开发出来了,并且已经托管到github上面去了,如果你在动手试验过程中有问题或者想运行现成的案例,可以直接访问我的项目地址download源码来直接运行观看效果哦!

实现你人生中的第一个jQuery插件相关推荐

  1. 自己在项目中写的一个Jquery插件和Jquery tab 功能

    后台查询结果 PDFSearchResult实体类: [DataContract(Name = "PDFSearchResult")]public class PDFSearchR ...

  2. 18岁,赚到了人生中的第一个10W!

    大家好,我是九歌 今年我18岁,赚到了我人生中的第一个10W 截至2019年10月14日,我已经做了43天的公众号啦,粉丝也悄然增长到了1W8,感谢各位读者朋友给我的支持和鼓励. 相信大部分读者都是从 ...

  3. 自己动手写一个JQuery插件(第二篇)(转)

    1.Hold住,我们要开始动真格了! 是的,看到这个标题,你一定也和我一样迫不及待了,因为我们不像之前那篇教程一样小打小闹了,我们现在要动真格了,这次我们要写的插件是上个插件的增强版本.而这个插件包含 ...

  4. 所谓 jQuery 插件,怎样开发一个 jQuery 插件

    简单来说,所谓 jQuery 插件就是扩展在 jQuery 原型对象上的一个方法.通过扩展 jQuery 对象,每次调用 jQuery 对象的时候,对象里面都包含了我们自己所添加的那个方法. 一般插件 ...

  5. 如何编写一个Jquery插件

    首先我们来搞清楚一些关于Jquery插件的知识: 一.插件的种类: 封装对象方法的插件 这种插件是将对象方法封装起来,用于对通过选择器获取的jQuery对象进行操作,是最常见的一种插件 封装全局函数的 ...

  6. 发布一个jQuery插件:formStorage

    中午休息时,没有睡意,没事写了个jquery插件:formStorage. 原理很简单,通过本地存储机制(userData或者localStorage),存储表单中元素的状态到本地. 需要时可以把所存 ...

  7. 如何去定义一个jquery插件

    扩展jquery的时候.最核心的方法是以下两种: $.extend(object) 可以理解为jquery添加一个静态方法 $.fn.extend(object) 可以理解为jquery实例添加一个方 ...

  8. stickUp 一个 jQuery 插件

    这是一个简单的jQuery插件,它能让页面目标元素 "固定" 在浏览器窗口的顶部,即便页面在滚动,目标元素仍然能出现在设定的位置.此插件可以在多页面的网站上工作,也能在单页面上面实 ...

  9. 自己动手写一个jQuery插件(第二篇)

    hold住,我们要开始动真格了! 是的,看到这个标题,你一定也和我一样迫不及待了,因为我们不像之前那篇教程一样小打小闹了,我们现在要动真格了, 这次我们要写的插件是上个插件的增强版本.而这个插件包含主 ...

最新文章

  1. 软件工程方法论对我们开发软件有多大用处?谈谈你的看法。
  2. equals的用法的注意事项
  3. 注定一爆就完的ZAO ,为什么只是一剂社交毒药?
  4. 岁月在流逝,从阿里退下来接近70后程序猿带给我的启示
  5. window上安装mysql服务核心版(亲测可用)
  6. 微服务升级_SpringCloud Alibaba工作笔记0005---spring gateway非阻塞异步模型
  7. 关于网络编程中MTU、TCP、UDP优化配置的一些总结
  8. Docker如何更改存储库名称或重命名图像?
  9. [转载]Qlist的用法
  10. 数据集:工人与机床对日产量的影响
  11. DELMIA软件:机器人抓手工具制作
  12. vue开发移动端app-学习记录
  13. hdu 5145 NPY and girls 莫队
  14. 【测试】你的浏览器HOLD住HTML5吗?
  15. 十八万字《python从零到精通教程》第二版,贴心保姆教你从零变大神,学不会找我
  16. 【7gyy】笔者支招:巧设安全模式防攻击
  17. Linux安装配置MySQL8.0 打war包 启动项目
  18. 教你一招永久去除WPS广告
  19. 使用selenium和phantomjs解决爬虫中对渲染页面的爬取
  20. 安装centOS7报未知错误

热门文章

  1. Mac设置顶部菜单栏技巧?
  2. [美]杰克·韦尔奇《赢》
  3. 新手怎么做一个小程序?
  4. Keil4工程转keil5工程方法
  5. PyCharm4注册码
  6. ios王者荣耀服务器维护31号,王者荣耀iOS版3月31日无法更新怎么办 王者荣耀iOS玄雍危机版本无法更新解决方法...
  7. 英文赞美句子,大家应该看看
  8. cocos creator3.3.0休闲游戏(云浮消消乐)源码H5+安卓+IOS三端源码
  9. 通信类顶级会议及期刊
  10. 作业5 - 团队展示