DataTables源码分析(一)

时间:2023-03-08 18:45:43

DataTables源码分析

写在前面

作为一名常年奋战在java世界中的程序猿,当我接触到现在所谓的前端技术时,内心其实是崩溃的。因为,前端的技术给我的第一个感觉就是“乱”,这里充斥着各种框架、插件和样式,往往由于版本和引入顺序等问题,造成不可描述的问题,轻者引发错误,无法实现效果;重者页面崩溃,分崩离析。

然而,前端技术作为一个web的重要部分,在整个系统中是不可或缺的,如果你要问我系统运行中比较前端和后端哪个更重要,我会毫不犹豫的说是前端。因为,从后端的角度看,现在的系统大都是与数据库打交道,将数据持久化,然后通过各种组合查询、计算,将数据提交给前端展现,这个过程都是可控的;而前端面对用户的使用,用户的操作其实是很复杂的,对用户的交互往往存在很多不确定性。所以,从这个角度看来,前端其实更加的难于处理和实现。当然如果您是做系统底层,使用大量复杂的数学算法,实现高效的系统功能,前面对于前端和后端的评价就当我没说,这种开发工作和开发者也是我最为钦佩的。

至于写这篇文章的目的,其实是作为个人接触前端的一个记录。前端的技术涵盖的范围是在很多、很杂,我日常的工作中接触最多的还是偏向管理系统的开发工作,所以前端技术更多偏向于使用JavaScript来实现页面的各种功能。而管理系统中最常见的就是表格,各类数据都要在表格中展现。看了一些页面的例子,常常会用到DataTables这个插件,我也试了试在页面中使用,效果不错。但作为一名有追求的程序猿,怎么能满足于只是简单对插件的使用层面呢!我想了解这样的插件是怎么实现的,而且能不能自己完成一个类似的插件,去掉一些不需要的功能,增加一些更贴近自己的需求的功能,这想来是极好的。不过,作为一个刚刚接触前端的小白,分析一个插件确实也是一件非常困难的事情,但是我想如果把这个插件分析完成,想来对于前端的JavaScript相关技术也会有一个长足的进步吧。

下面就开始我的探索之旅,可能会用很长时间来完成哦。

插件的实现

首先,我需要准备一个DataTables的插件源码和测试环境,插件是从官网下载的https://www.datatables.net/,另外还需要jQuery,就可以完成最基本的表格了。

<head>
  <meta charset="utf-8">
  <title></title>
  <link rel="stylesheet" href="../stylesheet/css/jquery.dataTables.css">
</head>
<body>
  <table id="example" class="display" cellspacing="0" width="100%">
.
.
.
  </table>

  <script src="../js/jquery-3.1.1.js" charset="utf-8"></script>
  <script src="../js/jquery.dataTables.js" charset="utf-8"></script>
  <script type="text/javascript">
    $(document).ready(function() {
       $('#example').dataTable();
    });
  </script>
</body>

可以看到,只要简单的引入jquery.dataTables.css样式和jquery-3.1.1.js、jquery.dataTables.js两个js文件,然后调用一下$('#example').dataTable();方法,就搞定了一个表格,把页面的table,变成了一个比较漂亮的,支持排序、搜索等功能的表格了。这个表格是dataTables官方例子的最简单的零配置的例子,效果如下:

DataTables源码分析(一)

这里,只有一个jquery.dataTables.js文件需要研究,打开这个文件,拉到文档末尾

DataTables源码分析(一)

1万5千多行代码!容我看一眼99年的asp压压惊,那时候天是那样的蓝,空气也是那样的清新,代码也没有这么长......

好吧,是我想多了,什么时候代码都是很长的,还是研究一下代码吧,大体看一下,整个代码分成了两个部分:

(
  fuction(factory){  //函数一
    ...
  }
  (function($, window, document, undefined){ 函数二
    ...
  })
);

函数一其实并不长,只是判断了三种情况对函数二的调用,一个是遵循AMD标准的,一个是CommonJS的,还有其他的情况。AMD和CommonJS就不展开研究了,之前看过以为大哥写的对于datatables不支持requireJS的解决办法,应该那个时候datatables对AMD规范还不支持,现在看来已经可以支持了,不需要自己在requireJS环境中手工调用了。函数一应该是datatables后来增加的一个小帽,用来支持不同的情况对下面函数二的调用,而函数二才是整个插件的主体,全部的关于插件的代码也都在函数二中完成。函数一在页面加载后会直接调用,函数二不会直接调用,但是会被函数一通过factory调用:

factory( jQuery, window, document );

我们顺着这个最简单的例子的调用来分析,这个例子中只是通过jQuery的选择器,得到了页面上table的对象,之后调用对象的dataTable();方法,就实现了表格的加载。

这里的有一个问题,就是页面的对象本身是没有dataTable方法的,这个方法是怎么加载到table对象上的呢?我们去看函数二,在函数的末尾有这样几句话:

```

// jQuery access

$.fn.dataTable = DataTable;

// Provide access to the host jQuery object (circular reference)
DataTable.$ = $;

// Legacy aliases
$.fn.dataTableSettings = DataTable.settings;
$.fn.dataTableExt = DataTable.ext;

// With a capital `D` we return a DataTables API instance rather than a
// jQuery object
$.fn.DataTable = function ( opts ) {
    console.log('1111');
    return $(this).dataTable( opts ).api();
};

```

$.fn.dataTable = DataTable;这句是向jQuery增加了一个函数,这个函数的函数名叫做dataTable,看看这不就是上面在table对象上调用的函数吗!这里要注意,$('#example'),得到的是一个jQuery对象,而不是html的页面元素,通过这个我猜测所有的选择器得到的对象,应该都继承自jQuery对象,这样就可以使用jQuery对象的方法了。

查了一下$.fn其实就等同于jQuery.prototype,也就是说dataTable函数被定义到了jQuery的原型中,所有继承自jQuery的对象,都可以使用这个函数。关于原型的概念,请自行百度或者参考《JavaScript高级程序设计》,这本书中有非常详细的描述(当然,其他书中也有,我是看的这本书了解的)。以后有时间会针对原型单独写一篇文章来介绍这个JavaScript中最奇怪的对象。

到这里,我们基本了解了插件的触发过程,我们如果要自定义一个插件,也可以做类似的实现,就是把一个函数定义到$.fn中,之后页面上通过jQuery得到元素,并调用我们自定义的方法,就可以对这个元素进行操作,也就完成了一个插件的最基本的定义。

$.fn.dataTable = DataTable;一句把dataTable函数指向了DataTable,而DataTable是这个js中定义的一个函数:

var DataTable = function ( options ) { ... }

接下来,我们会继续深入分析这个函数,以及相关的内容。