Parser解析器

疑问

  1. 为什么我们在页面html中编写class为easyui-xxx开头的组件,页面渲染后会自动展现对应的组件样式和功能?
  2. 为什么我们在页面加载完成后通过事件方法添加的带有easyui-xxx的网页组件不生效?

认识Parser解析器

  • 它是EasyUI的基础组件,支撑整个EasyUI框架能够正常使用。
  • 在网页渲染过程中,自动解析网页中定义的EasyUI组件。
  • 在网页结构变化时,能够手动去解析相关的EasyUI组件。

源码分析

在这里插入图片描述

  • 源码位于easyui包目录下的src目录中。
  • 因为easyui依赖于jQuery包,所以所有的方法、对象都追加到jQuery对象的上或原型链上。

1. easyui对象

$.easyui = {
    //获取元素在数组中的位置
    indexOfArray: function(a, o, id){},
    
    //移除数组元素
    removeArrayItem: function(a, o, id){},
    
    //添加或更新数组元素
    addArrayItem: function(a, o, r){},
    
    //获取数组中元素
    getArrayItem: function(a, o, id){},
    
    //遍历数组元素
    forEach: function(data, deep, callback){}
};

1.1 indexOfArray方法

参数信息

  1. 数组对象。
  2. 需要获取下标的数组元素(基本数据类型)或需要获取下标的数组元素的属性名(对象)。
  3. 若需要获取下标的数组元素是对象,则该值为对象对应判断属性的值。

返回值

  • 元素在数组中的下标位置。
示例一:基本数据类型数组
var items = [12, 34, 45, "李四"];
var index = $.easyui.indexOfArray(items, "李四");//3

基本数据类型使用时,只需要传入数组对象和需要获取下标的数据值。

示例二:对象数组,获取对象所在数组的下标值
var items = [{
    name: "张三",
    age: 12
}, {
    name: "李四",
    age: 16
}, {
    name: "王五",
    age: 32
}];
var index = $.easyui.indexOfArray(items, "name", "李四"); //1

1.2 getArrayItem方法

参数信息

  1. 数组对象。
  2. 需要获取下标的数组元素(基本数据类型)或需要获取下标的数组元素的属性名(对象)。
  3. 若需要获取下标的数组元素是对象,则该值为对象对应判断属性的值。

返回值

  • 获取存在于数组中的元素信息。
示例:根据数组元素对象的指定属性名值获取指定的数组元素对象
var items = [{
    name: "张三",
    age: 12
}, {
    name: "李四",
    age: 16
}, {
    name: "王五",
    age: 32
}];
var obj = $.easyui.getArrayItem(items, "name", "李四");//{name: "李四", age: 16}

1.3 addArrayItem方法

参数信息

  1. 数组对象。
  2. 需要获取下标的数组元素(基本数据类型)或需要获取下标的数组元素的属性名(对象)。
  3. 要插入数组的对象值。
示例一:向数组中插入元素对象,若存在,则更新对象
var items = [{
    name: "张三",
    age: 12
}, {
    name: "李四",
    age: 16
}, {
    name: "王五",
    age: 32
}];
$.easyui.addArrayItem(items, "name", {
    name: "赵云",
    age: 40
});

在这里插入图片描述

var items = [{
    name: "张三",
    age: 12
}, {
    name: "李四",
    age: 16
}, {
    name: "王五",
    age: 32
}];
$.easyui.addArrayItem(items, "name", {
    name: "李四",
    age: 40
});

在这里插入图片描述

1.4 removeArrayItem方法

参数信息

  1. 数组对象。
  2. 要移除数组元素值(基本类型数据)或移除对象的某个属性名
  3. 要移除对象的某个属性名对应的值。
示例一:移除数组中对象元素
var items = [{
    name: "张三",
    age: 12
}, {
    name: "李四",
    age: 16
}, {
    name: "王五",
    age: 32
}];
$.easyui.removeArrayItem(items, "name", "李四");

在这里插入图片描述

示例二:移除数组中除字符串外基本数据类型元素
var items = [{
    name: "张三",
    age: 12
}, {
    name: "李四",
    age: 16
}, {
    name: "王五",
    age: 32
}, 12];
$.easyui.removeArrayItem(items, 12);

在这里插入图片描述

注:不能移除字符串类型元素(第二个参数若为字符串,只能是数组元素对象的某个属性值必须配合第三个元素使用)。

1.5 forEach方法

参数信息

  1. 要遍历的数组
  2. 是否深度遍历,true-深度遍历,false-只遍历第一层。
  3. 遍历数组时的回调方法,参数为数组元素对象,返回false可阻止继续遍历。
示例一:遍历并筛选出符合条件元素(不深度遍历)
var items = [{
    name: "张三",
    age: 12
}, {
    name: "李四",
    age: 16
}, {
    name: "王五",
    age: 32
}, {
    name: "赵云",
    age: 25,
    children: [{
        name: "王麻子",
        age: 24
    }]
}];
var resultItems = [];
$.easyui.forEach(items, false, function(node) {
    if (node.age < 25) {
        resultItems.push(node);
    }
});
console.log(resultItems);

在这里插入图片描述

示例二:遍历并筛选出符合条件元素(深度遍历)
var items = [{
    name: "张三",
    age: 12
}, {
    name: "李四",
    age: 16
}, {
    name: "王五",
    age: 32
}, {
    name: "赵云",
    age: 25,
    children: [{
        name: "王麻子",
        age: 24
    }]
}];
var resultItems = [];
$.easyui.forEach(items, true, function(node) {
    if (node.age < 25) {
        resultItems.push(node);
    }
});
console.log(resultItems);

注意:该方法的第二个参数。

在这里插入图片描述

2. parser对象

// 是否自动解析
auto: true,
// 空函数
emptyFn: function(){},
// 解析完成后回调方法,一般用于重写
onComplete: function(context){},
// 组件名数组,用来识别组件
plugins:[],
// 解析标签
parse: function(context){},
// 解析高度或宽度值	
parseValue: function(property, value, parent, delta){},
// 解析组件的属性
parseOptions: function(target, properties){},
// 解析并设置网页盒子模型或固定定位
parseVars: function(){}

2.1 emptyFn方法

待使用的空方法。

2.2 onComplete方法

解析指定选择器的网页元素内easyui组件后的回调方法。

参数信息

  1. context
    • 传入的选择器字符串;例如:‘#xxx’、'.xxx’等
示例一:解析整个网页
var htm = "<div id=\"mypanel\" class=\"easyui-panel\" title=\"Basic Panel\" style=\"width: 400px; height: 200px;\"></div>";

$("body").append(htm);

$.parser.onComplete = function(context) {
    console.log("解析完成!");
    console.log(context);
}

$.parser.parse();
  • 若parse方法不传参数表示解析整个网页。
  • parse方法可传入选择器字符串,表示解析其下子内容。

2.3 plugins组件数组

  • easyui里面所有组件名都在此定义,在页面解析组件时会判断是否是easyui组件来控制是否解析组件。
  • 若我们自定义组件,必须在此插件数组中追加组件名,不然在页面中无法自动解析组件。
组件集合概述
序号组件名描述
1draggable拖动
2droppable放置
3resizable调整大小
4pagination分页
5tooltip提示框
6linkbutton按钮
7menu菜单
8sidemenu侧栏菜单
9menubutton菜单按钮
10splitbutton分割按钮
11switchbutton开关按钮
12progressbar进度条
13radiobutton单选按钮
14checkbox复选框
15tree
16textbox文本框
17passwordbox密码框
18maskedbox掩码框
19filebox文本框
20combo组合
21combobox组合框
22combotree组合树
23combogrid组合网格
24combotreegrid树形表格下拉框
25tagbox标签框
26numberbox数字框
27validatebox验证框
28searchbox搜索框
29spinner调整器
30numberspinner数字调整器
31timespinner时间调整器
32datetimespinner日期时间调整器
33calendar日历控件
34datebox日期控件
35datetimebox日期时间控件
36timepicker时间选择器
37slider滑块
38layout布局组件
39panel面板组件
40datagrid表格
41propertygrid属性表格
42treegrid树形表格
43datalist数据列表
44tabs选项卡
45accordion手风琴
46window弹框
47dialog对话框
48form表单

2.4 parseVars方法

用于控制easyui框架在流程里面的解析流程。

parseVars: function() {
    // 校验网页的盒子模型,盒子的width是否包含内边距padding
    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();
}
  • $._boxModel为false,表示盒子的width包含了border宽度和padding的宽度。
  • $._positionFixed为true,表示是否支持固定定位,true表示支持,false表示不支持。

2.5 parseOptions方法

用于解析easyui组件的data-options相关属性。

parseOptions: function(target, properties) {
    var t = $(target);
    var options = {};

    //1. 判断标签中是否包含data-options属性设置,若有则直接解析设置的属性放置到options对象中。
    var s = $.trim(t.attr('data-options'));
    if (s) {
        if (s.substring(0, 1) != '{') {
            s = '{' + s + '}';
        }
        options = (new Function('return ' + s))();
    }
    
    //2. 解析标签中style属性中有关像素大小设置的属性,并放置到options对象中
    $.map(['width', 'height', 'left', 'top', 'minWidth', 'maxWidth', 'minHeight', 'maxHeight'], function(p) {
        var pv = $.trim(target.style[p] || '');
        if (pv) {
            if (pv.indexOf('%') == -1) {
                pv = parseInt(pv);
                if (isNaN(pv)) {
                    pv = undefined;
                }
            }
            options[p] = pv;
        }
    });
	//3. 解析标签中其他属性,并将这些属性设置以对应基础类型放置到options对象中
    if (properties) {
        var opts = {};
        for (var i = 0; i < properties.length; i++) {
            var pp = properties[i];
            if (typeof pp == 'string') {
                opts[pp] = t.attr(pp);
            } else {
                for (var name in pp) {
                    var type = pp[name];
                    if (type == 'boolean') {
                        opts[name] = t.attr(name) ? (t.attr(name) == 'true') : undefined;
                    } else if (type == 'number') {
                        opts[name] = t.attr(name) == '0' ? 0 : parseFloat(t.attr(name)) || undefined;
                    }
                }
            }
        }
        $.extend(options, opts);
    }
    
    //4. 返回解析后的组件属性对象
    return options;
}
示例一:解析标签的相关属性,获取easyui组件需要的属性值
var htm = "<div id=\"mypanel\" class=\"easyui-panel\" title=\"基础面板\" style=\"width:700px;height:200px; padding:10px;\" data-options=\"content:'面板内容'\"></div>";
            $("body").append(htm);

var options = $.parser.parseOptions(document.querySelector('#mypanel'));
console.log(options);

在这里插入图片描述

注:参数的target需要传入js原生选择器获取的值。

2.6 parseValue方法

// property -- 属性名,例如:width
// value	-- 属性值,例如:100%
// parent	-- 该元素的父元素
// delta	-- 偏移值
parseValue: function(property, value, parent, delta) {
    // 1. 若偏移值不设置,则为0
    delta = delta || 0;
    var v = $.trim(String(value || ''));
    // 2. 获取值的后缀符号,如果是%,表示相对值,计算像素值
    var endchar = v.substr(v.length - 1, 1);
    if (endchar == '%') {
        v = parseFloat(v.substr(0, v.length - 1));
        // 3. 判断是设置width宽度还是height高度,通过父元素来获取
        if (property.toLowerCase().indexOf('width') >= 0) {
            delta += parent[0].offsetWidth - parent[0].clientWidth;
            v = Math.floor((parent.width() - delta) * v / 100.0);
        } else {
            delta += parent[0].offsetHeight - parent[0].clientHeight;
            v = Math.floor((parent.height() - delta) * v / 100.0);
        }
    } else {
        v = parseInt(v) || undefined;
    }
    // 4. 返回计算后的值
    return v;
}

认识clientWidth、offsetWidth的区别?

  • clientWidth:对象内容的可视区的宽度,不包滚动条等边线,会随对象显示大小的变化而改变
  • offsetWidth:对象整体的实际宽度,包滚动条等边线,会随对象显示大小的变化而改变。
示例一:panel组件中使用示例

在这里插入图片描述

2.7 parse方法

解析指定元素或者整个网页body的easyui组件信息。

parse: function(context) {
    // 存放easyui组件名数组,元素结构为:{name: 组件名, jq: 对应的组件jq对象}
    var aa = [];
    
    // 1.遍历获取指定元素中的所有涉及到的easyui组件
    for (var i = 0; i < $.parser.plugins.length; i++) {
        var name = $.parser.plugins[i];
        var r = $('.easyui-' + name, context);
        if (r.length) {
            if (r[name]) {
                r.each(function() {
                    $(this)[name]($.data(this, 'options') || {});
                });
            } else {
                aa.push({ name: name, jq: r });
            }
        }
    }
    
    // 2. 通过easyloader组件载入对应的组件
    if (aa.length && window.easyloader) {
        var names = [];
        for (var i = 0; i < aa.length; i++) {
            names.push(aa[i].name);
        }
        easyloader.load(names, function() {
            for (var i = 0; i < aa.length; i++) {
                var name = aa[i].name;
                var jq = aa[i].jq;
                jq.each(function() {
                    $(this)[name]($.data(this, 'options') || {});
                });
            }
            
            // 3. 回调解析成功事件
            $.parser.onComplete.call($.parser, context);
        });
    } else {
        $.parser.onComplete.call($.parser, context);
    }
}
示例一:解析指定网页部分
<div id="mydiv"></div>
<script type="text/javascript">
    $(function() {
        var htm = "<div id=\"mypanel\" class=\"easyui-panel\" title=\"基础面板\" style=\"width:700px;height:200px; padding:10px;\" data-options=\"content:'面板内容'\"></div>";
        $("#mydiv").append(htm);

        $.parser.parse($("#mydiv"));
    });
</script>

注:只能解析指定元素其下子或孙子节点的网页元素。

示例二:解析整个网页
<div id="mydiv"></div>
<script type="text/javascript">
    $(function() {
        var htm = "<div id=\"mypanel\" class=\"easyui-panel\" title=\"基础面板\" style=\"width:700px;height:200px; padding:10px;\" data-options=\"content:'面板内容'\"></div>";
        $("#mydiv").append(htm);

        $.parser.parse();
    });
</script>

注:解析整个网页body里面的内容。

解析时机

在这里插入图片描述

在网页标签渲染完成后,easyloader简单加载器构建之前触发解析网页操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值