jQuery EasyUI parser

郝修为
2023-12-01

jQuery EasyUI parser 的使用场景



parser,故名意思,就是解析器的意思,别看他只有那么几行代码,jQuery Easyui 能够根据class就能正常渲染页面全靠它了。一般情况下,我们并用不到解析器,本文主要讨论一下,什么情况下会用到它,如何使用。

自动调用parser:

我们之所以在页面中,只要书写相应的class,Easyui就能成功渲染页面,这是因为解析器在默认情况下,会在文档装载完成的时候($(document).ready)被调用一次,而且是渲染整个页面。

手动调用parser:

有些童鞋反映,当页面装载完后,如果用javascript生成的DOM中包含了Easyui支持控件的class,比如说,用javascript生成了以下代码:

1

<divclass="easyui-accordion"id="tt">

2

        <divtitle="title1">1</div>

3

    <divtitle="title2">2</div>

4

</div>

虽然页面上有这样的DOM了,但是没有被渲染为Easyui的accordion插件,原因很简单,Easyui并不会一直监听页面,所以不会主动渲染,这时候就需要手工调用Easyui的parser进行解析了。不过手工调用需要注意以下几点:

(1) 解析目标为指定DOM的所有子孙元素,不包含这个DOM自身:

比如上面代码生成的HTML,id="tt"是我们想要的手风琴DIV,像下面代码去手工解析的话是得不到你想要的结果的:

1

$.parser.parse($('#tt'));

道理很简单,parser只渲染tt的子孙元素,并不包括tt自身,而它的子孙元素并不包含任何Easyui支持的控件class,所以这个地方就得不到你想要的手风琴效果了,应该这样写:

1

$.parser.parse($('#tt').parent());

渲染tt的父节点的所有子孙元素就可以了,个人觉得通过jQuery的parent()方法是最安全不过的了,不管你的javascript输出了什么DOM,直接渲染其父节点就可以保证页面能被正确解析。

(2) 某些组件无法多次解析同一个DOM元素:

如果页面上本身就有tt元素:

1

<divclass="easyui-accordion"id="tt">

2

</div>

页面装载完,你通过脚本向tt元素append两个子DIV,然后解析:

1

$('#tt').append('<div title="title1">1</div><div title="title2">2</div>')

2

$.parser.parse($('#tt').parent());

不要以为你会得到一个满意的accordion,你什么也得不到,因为页面初始化的时候parser就主动渲染过tt元素,这时候tt已经被parser重构,你再到脚本中append,得到的DOM结构,其实并不是你预想的结果了,所以要避免这种用法。

parser组件作为easyui的基础类组件,其实担当者相当重要的角色,我们之所以能够通过定义一些样式就能完成对页面的自动渲染,完全是依靠parser组件;同时parser组件内部还定义了公用的属性转化器等几个实用工具,话不多说了,直接上带有注释的代码:

1    /**
2     * jQuery EasyUI 1.3.1
3     * Licensed under the GPL terms
4     * To use it on other terms please contact us
5     * Copyright(c) 2009-2012 stworthy [ stworthy@gmail.com ]
6     * (function($){})(jQuery) 定义一个匿名函数,并将jQuery对象作为实参传给这个匿名函数运行之。
7     *
8     */
9    (function($){
10        //在jQuery对象定义全局属性parser,parser属性也是对象,其自身又包含:auto,onComplete,plugins,parse,parseOptions这几个属性。
11        $.parser = {
12            //设置是否自动渲染页面(或者为DOM块)的开关
13            auto: true,
14            //渲染完成后会触发onComplete事件(如果该事件绑定了处理函数,则每次调用parser渲染DOM后都会触发一次该事件绑定的处理函数)
15            onComplete: function(_1){
16            },
17            //plugins属性枚举出了所有组件名称标识。
18            plugins: ["draggable", "droppable", "resizable", "pagination", "linkbutton", "menu", "menubutton", "splitbutton", "progressbar", "tree", "combobox", "combotree", "combogrid", "numberbox", "validatebox", "searchbox", "numberspinner", "timespinner", "calendar", "datebox", "datetimebox", "slider", "layout", "panel", "datagrid", "propertygrid", "treegrid", "tabs", "accordion", "window", "dialog"],
19            //parse就是实现渲染DOM的核心方法了,入参为DOM对象,其实也就是某个DOM块,不传入参的话,则是对整个页面进行渲染。
20            parse: function(_2){
21                var aa = [];
22                for (var i = 0; i < $.parser.plugins.length; i++) {
23                    var _3 = $.parser.plugins[i];
24                    //查找指定DOM下的特定的easyui组件,即以_2为上下文查找_3组件对应的DOM对象,_2为空的话,则在整个document为上下文。
25                    var r = $(".easyui-" + _3, _2);
26                    if (r.length) {
27                        if (r[_3]) {
28                            //调用plugins某个里_3组件对象的构造函数,上下文当然也就是r对象自身了,也就是构造函数里面使用的this
29                            //这个地方不要犯晕,r[_3]其实是function类型,其实也就是各个组件对应的构造函数。
30                            //例如panel组件的代码里总有这样的定义:$.fn.panel = function(jq, options){...},这个匿名函数我就称之为组件的构造函数(这个称呼只是个约定)。
31                            //而jQuery扩展fn的话等于扩展了全局方法到jQuery对象上,也就是所有的jQuery对象都具备了panel这个方法,
32                            //如果没有使用easyloader的话,r对应其实已经具备了easyui所有组件的构造函数。
33                            //这个地方如果不理解的话,请去翻阅jQuery的对象模型以及继承关系方面的资料。
34                            r[_3]();
35                        }
36                        else {//这个else分支也只有在使用easyloader的时候才会调用到了
37                            aa.push({
38                                name: _3,
39                                jq: r
40                            });
41                        }
42                    }
43                }
44                if (aa.length && window.easyloader) {
45                    var _4 = [];
46                    for (var i = 0; i < aa.length; i++) {
47                        _4.push(aa[i].name);
48                    }
49                    easyloader.load(_4, function(){
50                        for (var i = 0; i < aa.length; i++) {
51                            var _5 = aa[i].name;
52                            var jq = aa[i].jq;
53                            //调用组件的构造函数
54                            jq[_5]();
55                        }
56                        $.parser.onComplete.call($.parser, _2);
57                    });
58                }
59                else {
60                    //这地方调用绑定的onComplete事件,入参为_2这个上下文。
61                    //为什么这个写法?还不是想把_2作为参数传给onComplete事件绑定的函数处理程序嘛。
62                    $.parser.onComplete.call($.parser, _2);
63                }
64            },
65            //公用的属性转换器,兼容data-options方式和老方式,功能可谓灵活而强大。
66            parseOptions: function(_6, _7){
67                var t = $(_6);
68                var _8 = {};
69                var s = $.trim(t.attr("data-options"));
70                if (s) {
71                    var _9 = s.substring(0, 1);
72                    var _a = s.substring(s.length - 1, 1);
73                    if (_9 != "{") {
74                        s = "{" + s;
75                    }
76                    if (_a != "}") {
77                        s = s + "}";
78                    }
79                    _8 = (new Function("return " + s))();
80                }
81                if (_7) {
82                    var _b = {};
83                    for (var i = 0; i < _7.length; i++) {
84                        var pp = _7[i];
85                        if (typeof pp == "string") {
86                            if (pp == "width" || pp == "height" || pp == "left" || pp == "top") {
87                                _b[pp] = parseInt(_6.style[pp]) || undefined;
88                            }
89                            else {
90                                _b[pp] = t.attr(pp);
91                            }
92                        }
93                        else {
94                            for (var _c in pp) {
95                                var _d = pp[_c];
96                                if (_d == "boolean") {
97                                    _b[_c] = t.attr(_c) ? (t.attr(_c) == "true") : undefined;
98                                }
99                                else {
100                                    if (_d == "number") {
101                                        _b[_c] = t.attr(_c) == "0" ? 0 : parseFloat(t.attr(_c)) || undefined;
102                                    }
103                                }
104                            }
105                        }
106                    }
107                    $.extend(_8, _b);
108                }
109                return _8;
110            }
111        };
112        //文档准备好后,根据$.parser.auto的设置来决定是否自动渲染
113        $(function(){
114            if (!window.easyloader && $.parser.auto) {
115                $.parser.parse();
116            }
117        });
118        //扩展_outerWidth方法到jQuery对象上,用于兼容IE这种不是正规盒子模型的另类浏览器
119        $.fn._outerWidth = function(_e){
120            if (_e == undefined) {
121                if (this[0] == window) {
122                    return this.width() || document.body.clientWidth;
123                }
124                return this.outerWidth() || 0;
125            }
126            return this.each(function(){
127                if (!$.support.boxModel && $.browser.msie) {
128                    $(this).width(_e);
129                }
130                else {
131                    $(this).width(_e - ($(this).outerWidth() - $(this).width()));
132                }
133            });
134        };
135        //扩展_outerHeight方法到jQuery对象上,用于兼容IE这种不是正规盒子模型的另类浏览器
136        $.fn._outerHeight = function(_f){
137            if (_f == undefined) {
138                if (this[0] == window) {
139                    return this.height() || document.body.clientHeight;
140                }
141                return this.outerHeight() || 0;
142            }
143            return this.each(function(){
144                if (!$.support.boxModel && $.browser.msie) {
145                    $(this).height(_f);
146                }
147                else {
148                    $(this).height(_f - ($(this).outerHeight() - $(this).height()));
149                }
150            });
151        };
152        //获取/设置属性的方法(attributes和properties)。获取在匹配的元素集中的第一个元素的属性值。prop()方法应该被用来处理boolean attributes/properties以及在html(比如:window.location)中不存在的properties。其他所有的attributes(html 中你看到的那些)可以而且应该继续使用.attr()方法来进行操作。
153        $.fn._propAttr = $.fn.prop || $.fn.attr;
154    })(jQuery);






 类似资料:

相关阅读

相关文章

相关问答