EasyUI學習筆記(五)——學習讀源碼--parser源碼閱讀分析1

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.auto boolean 定義是否自動解析easyui組件 true
  • 事件
名稱 參數 描述
$.parser.onComplete context 當解析器完成解析動作的時候觸發
  • 方法
名稱 參數 描述
$.parser.parse context 解析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");
                }
            });
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章