现在的位置: 首页 > easyui > Form > combo > 正文
扩展的validatebox校验规则跑哪里去了
2013年03月04日 combo, combobox, validatebox ⁄ 共 4535字 评论数 2 ⁄ 被围观 10,103 views+
文章目录
[隐藏]

在使用EasyUI的时候,有时我们要改动某个组件的源码,因为jquery.easyui.min.js体积庞大,且格式混乱,所以我们往往选择修改位于plugins目录下的单个组件源码,然后在使用的时候先引入jquery.easyui.min.js文件再引入plugins/jquery.validatebox.js(这里拿validatebox组件说事)文件,这样就起到了覆盖定义的效果。

这样做到底有没有什么问题呢?在没有遇到问题的时候,我也是觉得应该没啥问题了。上周群内有兄弟问了一个validatebox扩展的rules无效的问题,我分析过后,禁不住拍了下脑门,原来这种覆盖定义的方式还是存在一定隐患的。我们拿依赖validatebox的combobox来还原”凶案现场“。

凶案现场:

文件引入顺序:
  1. <script type="text/javascript" src="../../jquery-1.8.0.min.js"></script>   
  2. <script type="text/javascript" src="../../jquery.easyui.min.js"></script>   
  3. <script type="text/javascript" src="../../plugins/jquery.validatebox.js"></script>   
  4. <script type="text/javascript">   
  5. //alert($.fn.validatebox.defaults.rules == $.fn.combo.defaults.rules);   
  6. $(document).ready(function () {   
  7.     $.extend($.fn.validatebox.defaults.rules, {   
  8.         IsExist: {   
  9.             validator: function (value) {   
  10.                 alert(11);   
  11.             }   
  12.         }   
  13.     });   
  14. });   
  15. </script>  
使用扩展的IsExist规则:
  1. <select id="abc" class="easyui-combobox" data-options="validType:'IsExist'" name="state" style="width:200px;">  
  2.     <option value="AL">ssadasdasdas</option>  
  3.     <option value="AK">Alaska</option>  
  4.     <option value="AZ">Arizona</option>  
  5.     <option value="AR">Arkansas</option>  
  6.     <option value="CA">California</option>  
  7. </select>  

结果让人出乎意料呀,我们扩展的IsExist规则并未被触发,这是怎么回事呢?

问题分析:

要弄清楚这个问题,我们必须把关键步骤梳理出来,也就是要把关键代码的执行顺序给梳理出来,这一点对于分析问题很重要。经过简单分析,可以得到关键代码的执行顺序如下:

1.定义validatebox组件

jquery.easyui.min.js内部首先引入的是validatebox组件,组件的定义方式都是自动运行的匿名函数,匿名函数内部定义组件的构造函数,默认值,方法,属性转换器等,对于本文要分析的问题,我们把重点放在默认值和属性转换器的定义上:

1-1.定义默认值:
  1. $.fn.validatebox.defaults = {   
  2.     required: false,   
  3.     //...省略若干属性   
  4.     rules: {   
  5.         url: {   
  6.             validator: function(value) {   
  7.                 return false;//这里就不写那串正则表达式了   
  8.             },   
  9.             message: "Please enter a valid URL."  
  10.         }   
  11.         //...省略若干规则   
  12.     }   
  13. };  

我们看到定义了$.fn.validatebox.defaults属性,而这个属性指向一个内存堆,我们姑且将这个堆叫做:A;defaults属性内部还有一个rules属性,rules也是一个对象,指向另一内存堆:B.

2.定义combo组件

combo组件依赖validatebox组件,所以后于validatebox组件引入,引入combo的时候自然也会定义combo的构造函数,默认值,方法,属性转换器等。

2-1.定义默认值:
  1. $.fn.combo.defaults = $.extend({}, $.fn.validatebox.defaults, {   
  2.     width: "auto",   
  3.     //省略若干属性,注意的是combo的默认值并没有显式地申明rules属性   
  4.     //组件间属性的继承是通过extend函数实现的,extend函数的第二个实参就是validatebox的默认属性   
  5. });  
3.定义combobox组件

combobox组件依赖combo组件,所以后于combo组件引入,引入combobox的时候自然也会定义combobox的构造函数,默认值,方法等,属性转换器。

3-1.定义默认值:
  1. $.fn.combobox.defaults = $.extend({}, $.fn.combo.defaults, {   
  2.     valueField: "value"  
  3.     //此处省略属性属性若干   
  4.     //combobox同样适用extend函数实现部分属性继承自combo   
  5. });  

到这步为止,我们的validatebox,combo,combobox组件都具有rules属性,因其实通过extend实现的,所以他们的rules属性指向同一个内存堆:B

4.重新定义validatebox组件

因为我们在jquery.easyui.min.js之后又引入了jquery.validatebox.js文件,等于重新定义了一遍validatebox组件,期间必要重新定义默认值和属性转换器。

4-1.重新定义默认值:
  1. $.fn.validatebox.defaults = {   
  2.     required: false,   
  3.     //...省略若干属性   
  4.     rules: {   
  5.         url: {   
  6.             validator: function(value) {   
  7.                 return false;//这里就不写那串正则表达式了   
  8.             },   
  9.             message: "Please enter a valid URL."  
  10.         }   
  11.         //...省略若干规则   
  12.     }   
  13. };  

重新定义了$.fn.validatebox.defaults属性,而这个属性指向新的内存堆,我们将这个堆叫做:C;defaults属性内部的rules属性也指向另一新的内存堆:D.

而这时候combo和combobox的rules属性却依旧指向内存堆B,这就为后面扩展rules属性无效问题埋下了凶案现场的定时炸弹。

5.注册一个document.ready事件

注册document.ready事件是在parser组件内完成的,document.ready事件内部负责解析渲染页面内发现的EasyUI组件。

6.构造combobox组件

parser组件发现页面存在combobox关键class,开始调用combobox构造函数初始化combobox组件。

7.构造combo组件

combobox组件依赖combo组件,故在combobox初始化的时候会同时构造combo组件的实例。

8.构造validatebox组件

combo组件依赖validatebox组件,故在combo初始化的时候会同时构造validatebox组件的实例。

9.执行开发者扩展rules的代码

最后才是运行开发者注册的document.ready事件里面的代码,也就是扩展validatebox组件rules属性的代码:

  1. $(document).ready(function() {   
  2.     $.extend($.fn.validatebox.defaults.rules, {   
  3.         IsExist: {   
  4.             validator: function(value) {   
  5.                 alert(11);   
  6.             }   
  7.         }   
  8.     });   
  9. });  

问题很明确了,这时候我们扩展的rules属性指向的是内存堆D,而前面也分析了combo和combobox的rules属性依旧指向内存堆B,理所当然,扩展的"IsExist"规则只能在validatebox内部使用了,在combo和combobox组件上无法使用,因为combo和combobox的rules属性压根就没被扩展过!

解决问题:

既然已经分析出原因,那么对这个问题我们也就有了偷懒的解决方式,那就是将扩展rules的代码放到引入jquery.validatebox.js代码的前面,同时不能将扩展rules的代码放到document.ready里面,即:

  1. <script type="text/javascript" src="../../jquery-1.8.0.min.js"></script>   
  2.     <script type="text/javascript" src="../../jquery.easyui.min.js"></script>   
  3.     <script type="text/javascript">   
  4.         $.extend($.fn.validatebox.defaults.rules, {   
  5.             IsExist: {   
  6.                 validator: function(value) {   
  7.                     alert(11);   
  8.                 }   
  9.             }   
  10.         });   
  11.     </script>   
  12.     <script type="text/javascript" src="../../plugins/jquery.validatebox.js"></script>  

目前有 2 条留言 其中:访客:1 条, 博主:1 条

  1. Gongle : 2013年03月06日15:16:01  -49楼 @回复 回复

    你好,jQuery easyui validatebox 验证事件时机,怎么修改啊,不需要keyup就验证,只需要blur验证就好,非常期望博主的回复.我的邮箱是skygongle@gmail.com.谢谢.


    • 管理员
      世纪之光 : 2013年03月06日16:46:49  地下1层 @回复 回复

      你好,我分析过validatebox的源码,对里面的事件绑定以及校验的实现原理分析得很清楚,你看完后应该就知道怎么改了,如果还是不清楚,可以进一步交流,文章地址:validatebox源码分析

给我留言

留言无头像?


×