花了点时间,看了下jQuery-template.js,不多废话,先上结构
jQuery.each({..},function(){}) jQuery.fn.extend({..}) jQuery.extend({...}) jQuery.extend(jQuery.tmpl,{..}) function xx(){}//自定义方法
结构上非常简单,但template插件却提供了不错的模版功能,我们根据API来慢慢看这个框架。
网络资源
如果在原型上添加方法,这一般都是暴露给外部调用的API,我们来看一下,各个方法的流程:
<script type="text/html" id="template1"> <tr> <td>${ID}</td> <td>${Name}</td> </tr> </script> <script type="text/javascript" src="jquery-1.9.1.min.js"></script> <script type="text/javascript" src="jquery.tmpl.js"></script> <script type="text/javascript"> var users = [ { ID: 'think8848', Name: 'Joseph Chan', Langs: [ 'Chinese', 'English' ] }, { ID: 'aCloud', Name: 'Mary Cheung', Langs: [ 'Chinese', 'French' ] } ]; $('#template1').tmpl(users).appendTo('#table1') </script>
可以看到模版被写在了type为text/html的script标签中,其中users是数据元,最后调用了一个$('#template1').tmpl(users)将信息写入模版,最后生成出的信息插入dom中,即完成。ok,来看一下jQuery原型上的tmpl方法
tmpl: function( data, options, parentItem ) { return jQuery.tmpl( this[0], data, options, parentItem );//页面调用的时候的入口方法,这会去调用jQuery上的tmpl方法 }
进入jQuery上的tmpl方法
tmpl: function( tmpl, data, options, parentItem ) { var ret, topLevel = !parentItem; if ( topLevel ) { // This is a top-level tmpl call (not from a nested template using {{tmpl}}) parentItem = topTmplItem;//{ key: 0, data: {} } tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl );//根据参数数量,选择性的执行jQuery.template方法,这里获得了一个先有正则匹配,再经过拼接,最后new Function而得到一个匿名函数 wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level } else if ( !tmpl ) { tmpl = parentItem.tmpl; newTmplItems[parentItem.key] = parentItem; parentItem.nodes = []; if ( parentItem.wrapped ) { updateWrapped( parentItem, parentItem.wrapped ); } jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) )); } if ( !tmpl ) { return []; // Could throw... } if ( typeof data === "function" ) {//传进来的数据看是否存在函数 data = data.call( parentItem || {} ); } if ( options && options.wrapped ) { updateWrapped( options, options.wrapped ); } ret = jQuery.isArray( data ) ? jQuery.map( data, function( dataItem ) { return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null; }) : [ newTmplItem( options, parentItem, tmpl, data ) ]; topLevel ? jQuery( build( parentItem, null, ret ) ) : ret; }
对于这个例子,我们需要看一下这段代码的几个部分
tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl );//根据参数数量,选择性的执行jQuery.template方法,这里获得了一个先有正则匹配,再经过拼接,最后new Function而得到一个匿名函数
tmpl参数则是那个写有模版的script对象,根据这个方法,我们进入jQuery.template方法。
//这里经过几次进入template方法,最终还是将type为text/html的script对象传入template方法的第二个参数中 template: function( name, tmpl ) { if (tmpl) { ( tmpl = buildTmplFn( tmpl ); } else if ( tmpl instanceof jQuery ) { tmpl = tmpl[0] || {};//获取dom对象否则赋空对象 } tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML )); } } name ? (typeof name !== "string" ? jQuery.template( null, name ): (jQuery.template[name] || jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null; }
这段代码中的一些逻辑判断,会在后面的API描述中介绍,我们先看到一个很重要的自定义方法buildTmplFn,这算是这个插件比较重要的一个部分。传入参数则是模版字符串