EasyUI学习笔记(五)——学习读源码--parser源码阅读分析1

23 篇文章 0 订阅
11 篇文章 0 订阅

Parser

parser模块是easyloader第一个加载的模块

在前面的笔记中,我们分析了easyloader源代码,知道easyui加载模块组件可以有2种方式:

  • 通过设置class属性的方式
  • 使用JavaScript的方式进行渲染

这本质上是通过parser解析器来实现的,一般是自动触发完成整个页面的解析。

parser主要作用

  • parser自动渲染:

    最主要的运用场景:
    只要我们书写相应的class,easyui就能成功的渲染页面。
    这是因为解析器在默认情况下,会在dom加载完成的时候($(docunment).ready)被调用,而且是渲染整个页面。

  • parser解析器手动渲染:

    需要手动调用的情况是:
    当页面已经加载完成,但是此时我们使用js生成的DOM中包含了easyui支持的class,并且我们也有将其渲染成easyui组件的需求。在这种情况下就需要手动调用parser

<div class="easyui-accordion" id="tt">
        <div title="title1">1</div>
<div title="title2">2</div>
</div>

当上面代码的生成是在easyui渲染界面完成之后,easyui不会一直监听页面,所以该段代码不会被渲染成“手风琴DIV”的样式。
此时就需要我们手动去渲染了。

  • 注意:

    解析目标位指定DOM的所有子孙元素,不包括DOM本身。

$parser.parser($('tt').parent())

并非

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

尽量不要多次解析同一个DOM元素(ID):页面初始化就已经主动渲染过dom节点了,你再次手动解析该dom节点时该dom已经被parser重构,得到的DOM就并非是你料想的结果,该方式应该尽量避免。

  • 用法总结
$.parser.parse();       // 不带参数,默认解析该页面中所有被定义为easyui组件的节点就是解析整个页面 
$.parser.parse('#cc');  // 带一个jquery选择器,使用这种方式我们可以单独解析局部的easyui组件节点

注意:

上面的id不能是为当前组件的id,必须为当前组件父容器的id。也就是说这个jquery选择器必须是解析组件的父级以上的节点,潜台词就是这个查找出来的节点相当于一个容器,它只会解析容器里面的内容。

<div id="cc">
    <div id="Window" class="easyui-window"></div>
</div>

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

这么使用id为Window的节点才会正常。

$.parser.parse();不传参是解析页面中所有定义为easyui组件的节点。

  • 特性
名称类型描述默认值
$.parser.autoboolean定义是否自动解析easyui组件true
  • 事件
名称参数描述
$.parser.onCompletecontext当解析器完成解析动作的时候触发
  • 方法
名称参数描述
$.parser.parsecontext解析easyui组件

  • parser源代码阅读分析笔记:

    源代码很多,只截取了部分主要的放了上来

    /**
     * parser模块主要作用是解析页面中easyui的控件
     */
    $.parser = {

        //是否自动解析
        auto : true,

        //渲染完成后会触发onComplete事件,若该事件绑定了处理函数,则每次调用parser渲染DOM后都会触发一次该事件绑定的处理函数
        onComplete : function(_b) {
        },

        //plugins属性枚举出了所有可以被parse解析的控件组件名称
        plugins : [ "draggable", "droppable", "resizable", "pagination",
                "tooltip", "linkbutton", "menu", "menubutton", "splitbutton",
                "switchbutton", "progressbar", "tree", "textbox",
                "passwordbox", "filebox", "combo", "combobox", "combotree",
                "combogrid", "combotreegrid", "numberbox", "validatebox",
                "searchbox", "spinner", "numberspinner", "timespinner",
                "datetimespinner", "calendar", "datebox", "datetimebox",
                "slider", "layout", "panel", "datagrid", "propertygrid",
                "treegrid", "datalist", "tabs", "accordion", "window",
                "dialog", "form" ],

        /**
         * function(context) 解析函数
         * 实现渲染DOM的核心方法,传入参数为DOM对象,其实也就是某个DOM块,不传入参的话,则是对整个页面进行渲染。
         */
        parse : function(_c) {

            var aa = [];

            for (var i = 0; i < $.parser.plugins.length; i++) {

                //  _d=name , 控件名字
                var _d = $.parser.plugins[i];

                // 查找指定DOM下的特定的easyui组件,也就是查找class为easyui-控件名字的jq对象,即以_c为上下文查找_d组件对应的DOM对象,比如:easyui-layout._c为空的话,则在整个document为上下文
                var r = $(".easyui-" + _d, _c);

                if (r.length) {

                    if (r[_d]) {    //如果有这个对象
                        /**
                         * 调用plugins某个里_d组件对象的类似于构造函数的那个匿名函数(就把它叫做构造函数了。。仅仅是因为叫起来方便)
                         * 上下文就是r对象自身了,也就是构造函数里面使用的this
                         * 这个地方容易晕,r[_d]其实是function类型,其实也就是各个组件对应的构造函数
                         * 例如panel组件的代码里有这样的定义:
                         *  $.fn.panel = function(jq, options){...}
                         * jQuery扩展fn的话等于扩展了全局方法到jQuery对象上,也就是所有的jQuery对象都具备了panel这个方法
                         * 如果没有使用easyloader的话,r对应其实已经具备了easyui所有组件的构造函数
                         */   
                        r.each(function() {
                            $(this)[_d]($.data(this, "options") || {});
                        });
                    } 
                    else {  //这个else分支也只有在使用easyloader的时候才会调用到
                        aa.push({
                            name : _d,
                            jq : r
                        });
                    }
                }
            }
            if (aa.length && window.easyloader) {
                var _e = [];
                for (var i = 0; i < aa.length; i++) {
                    _e.push(aa[i].name);
                }
                easyloader.load(_e, function() {
                    for (var i = 0; i < aa.length; i++) {
                        var _f = aa[i].name;
                        var jq = aa[i].jq;

                        //调用组件的构造函数
                        jq.each(function() {
                            $(this)[_f]($.data(this, "options") || {});
                        });
                    }
                    $.parser.onComplete.call($.parser, _c);
                });
            } 
            else {
                /**
                 * 调用绑定的onComplete事件
                 * 传入参数为上下文_c
                 * 目的就是把_c作为参数传给onComplete事件绑定的函数来处理程序
                 */
                $.parser.onComplete.call($.parser, _c);
            }
        },
        //公用的属性转换器
        parseValue : function(_10, _11, _12, _13) {
            _13 = _13 || 0;
            var v = $.trim(String(_11 || ""));
            var _14 = v.substr(v.length - 1, 1);
            if (_14 == "%") {
                v = parseInt(v.substr(0, v.length - 1));
                if (_10.toLowerCase().indexOf("width") >= 0) {
                    v = Math.floor((_12.width() - _13) * v / 100);
                } else {
                    v = Math.floor((_12.height() - _13) * v / 100);
                }
            } else {
                v = parseInt(v) || undefined;
            }
            return v;
        },
        parseOptions : function(_15, _16) {
            var t = $(_15);
            var _17 = {};
            var s = $.trim(t.attr("data-options"));
            if (s) {
                if (s.substring(0, 1) != "{") {
                    s = "{" + s + "}";
                }
                _17 = (new Function("return " + s))();
            }
            $.map([ "width", "height", "left", "top", "minWidth", "maxWidth",
                    "minHeight", "maxHeight" ], function(p) {
                var pv = $.trim(_15.style[p] || "");
                if (pv) {
                    if (pv.indexOf("%") == -1) {
                        pv = parseInt(pv);
                        if (isNaN(pv)) {
                            pv = undefined;
                        }
                    }
                    _17[p] = pv;
                }
            });
            if (_16) {
                var _18 = {};
                for (var i = 0; i < _16.length; i++) {
                    var pp = _16[i];
                    if (typeof pp == "string") {
                        _18[pp] = t.attr(pp);
                    } else {
                        for ( var _19 in pp) {
                            var _1a = pp[_19];
                            if (_1a == "boolean") {
                                _18[_19] = t.attr(_19) ? (t.attr(_19) == "true")
                                        : undefined;
                            } else {
                                if (_1a == "number") {
                                    _18[_19] = t.attr(_19) == "0" ? 0
                                            : parseFloat(t.attr(_19))
                                                    || undefined;
                                }
                            }
                        }
                    }
                }
                $.extend(_17, _18);
            }
            return _17;
        }
    };

    //文档准备好后,根据$.parser.auto的设置来决定是否自动渲染
    $(function() {
        var d = $(
                "<div style=\"position:absolute;top:-1000px;width:100px;height:100px;padding:5px\"></div>")
                .appendTo("body");
        $._boxModel = d.outerWidth() != 100;
        d.remove();
        d = $("<div style=\"position:fixed\"></div>").appendTo("body");
        $._positionFixed = (d.css("position") == "fixed");
        d.remove();
        if (!window.easyloader && $.parser.auto) {
            $.parser.parse();
        }
    });

    //扩展_outerWidth方法到jQuery对象上,用于兼容IE这种不是正规盒子模型的浏览器
    $.fn._outerWidth = function(_1b) {
        if (_1b == undefined) {
            if (this[0] == window) {
                return this.width() || document.body.clientWidth;
            }
            return this.outerWidth() || 0;
        }
        return this._size("width", _1b);
    };

    //扩展_outerHeight方法到jQuery对象上,用于兼容IE这种不是正规盒子模型的浏览器
    $.fn._outerHeight = function(_1c) {
        if (_1c == undefined) {
            if (this[0] == window) {
                return this.height() || document.body.clientHeight;
            }
            return this.outerHeight() || 0;
        }
        return this._size("height", _1c);
    };
    $.fn._scrollLeft = function(_1d) {
        if (_1d == undefined) {
            return this.scrollLeft();
        } else {
            return this.each(function() {
                $(this).scrollLeft(_1d);
            });
        }
    };
    $.fn._propAttr = $.fn.prop || $.fn.attr;
    $.fn._size = function(_1e, _1f) {
        if (typeof _1e == "string") {
            if (_1e == "clear") {
                return this.each(function() {
                    $(this).css({
                        width : "",
                        minWidth : "",
                        maxWidth : "",
                        height : "",
                        minHeight : "",
                        maxHeight : ""
                    });
                });
            } else {
                if (_1e == "fit") {
                    return this.each(function() {
                        _20(this, this.tagName == "BODY" ? $("body") : $(this)
                                .parent(), true);
                    });
                } else {
                    if (_1e == "unfit") {
                        return this.each(function() {
                            _20(this, $(this).parent(), false);
                        });
                    } else {
                        if (_1f == undefined) {
                            return _21(this[0], _1e);
                        } else {
                            return this.each(function() {
                                _21(this, _1e, _1f);
                            });
                        }
                    }
                }
            }
        } else {
            return this.each(function() {
                _1f = _1f || $(this).parent();
                $.extend(_1e, _20(this, _1f, _1e.fit) || {});
                var r1 = _22(this, "width", _1f, _1e);
                var r2 = _22(this, "height", _1f, _1e);
                if (r1 || r2) {
                    $(this).addClass("easyui-fluid");
                } else {
                    $(this).removeClass("easyui-fluid");
                }
            });
        }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值