实现你人生中的第一个jQuery插件
Posted 「已注销」
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现你人生中的第一个jQuery插件相关的知识,希望对你有一定的参考价值。
前言
本想把本篇取名:从0开始写前端UI框架:实现你人生中的第一个jQuery插件 ,但感觉标题太长,所以简单明了直接取后面主题为题目吧。
前一篇文章 已经对my-ui框架做了简单的介绍。谈到了我是如何想起做这个框架的,并描绘了这个框架的大致功能或者说是组件,文章最后举了个已经实现的table表格功能为例子,万里长征就从这里开始!接下来咱们就来剖析如何实现这一简单的功能了,我已经实现了一个table组件功能,也叫做插件,那么接下来你就要开始来了解什么是插件,以及如何写一个插件了。
预备知识
科普插件知识:插件(Plug-in,又称addin、add-in、addon或add-on,又译外挂)是一种遵循一定规范的应用程序接口编写出来的程序。其只能运行在程序规定的系统平台下(可能同时支持多个平台),而不能脱离指定的平台单独运行。因为插件需要调用原纯净系统提供的函数库或者数据。
简而言之,插件就是现有框架的补丁或扩展,jQuery的插件必须要依赖于jQuery库。学习插件开发之前,你最好具备以下知识:
- javascript面向对象思想,把这种脚本语言当成面向对象来看待。重点是提升你的JavaScript封装能力。你可以尝试封装一个带有四则运算能力的计算器对象,或者封装一个可以自由切换选项卡的对象,或者一个抽奖功能等。这里的重点是练习你的封装能力,而不是算法。
- 理解JavaScript中this的功能,当this处于js文件裸体内,当this处于函数内,当this处于对象内分别指向的是谁。
- 理解JavaScript中的原型以及原型链,搞明白对象属性和原型属性有什么区别,并且弄明白prototype关键字的用意。
- 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种:
- 第一种是工具集toolkit。就是平时开发中经常用到的代码段封装成,比如处理字符串的代码段,比如处理日期的函数,众多工具集合在一起就是一个toolkit了。
- 第二种是Libaray。在Vue,React以及Angluar出来之前,我们也称它们为框架,比如jQuery,BootStrap,以前我们一直以为它是一个框架,但是现在你去看它的官网,官方给它的定义是库。
- 第三种是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编程经验的开发者,你应该看到,这个代码段只做了两件事:
- ajax请求后台数据
- 拿到请求的数据循环遍历填充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设计中大概要求我们:
- 能动态接收请求数据地址url参数,必选
- http请求方式,可选,默认值为get
- 请求到的数据,可以每一列filed属性属性值填充数据
- 数据可能需要格式化,比如返回一个金额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以上是关于实现你人生中的第一个jQuery插件的主要内容,如果未能解决你的问题,请参考以下文章