JavaScript框架(xmlplus)组件的介绍(十)网格(DataGrid)
xmlplus 是一个JavaScript框架,用于快速开发前后端项目。这篇文章主要介绍了xmlplus组件设计系列之xmlplus网格,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
这一章我们要实现是一个网格组件,该组件除了最基本的数据展示功能外,还提供排序以及数据过滤功能。
数据源
为了测试我们即将编写好网格组件,我们采用如下格式的数据源。此数据源包含两部分的内容,分别是表头数据集和表体数据集。网格组件实例最终的列数由表头数据集的长度决定。
var data = { gridColumns: ['name', 'power'], gridData: [ { name: 'Chuck Norris', power: Infinity }, { name: 'Bruce Lee', power: 9000 }, { name: 'Jackie Chan', power: 7000 }, { name: 'Jet Li', power: 8000 } ] };
顶层设计
从视觉上,我们很自然地把网格组件划分为表头与表体。此网格组件有三个功能,所以应该提供三个动态接口。但我们注意到排序功能是通过点击表头进行的,而表头属于网格组件的一部分,所以该功能应该内置。从而,实际上我们的网格组件对外只暴露两个动态接口:一个用于过滤,另一个用于接收数据源。所以我们可以得到如下的一个顶层设计。
DataGrid: { xml: `<table id='table'> <Thead id='thead'/> <Tbody id='tbody'/> </table>`, fun: function (sys, items, opts) { function setValue(data) { items.thead.val(data.gridColumns); items.tbody.val(data.gridColumns, data.gridData); } function filter(filterKey) { // 过滤函数 } return { val: setValue, filter: filter }; } }
设计表头
表头只有一行,所以可以直接给它提供一个 tr 元素。tr 元素的子级项 th 的个数取决于表头数据集的长度,所以需要动态创建。由于 th 元素包含了排序功能,所以需要另行封装。下面是我们给出的表头的设计。
Thead: { xml: `<thead id='thead'> <tr id='tr'/> </thead>`, fun: function (sys, items, opts) { function setValue(value) { sys.tr.children().call("remove"); data.forEach(item => sys.tr.append("Th").value().val(item)); } return { val: setValue }; } }
表头数据项组件提供一个文本设置接口。该组件本身并不负责排序,它只完成自身视图状态的变更以及排序命令的派发。排序命令的派发需要携带两个数据:一个是排序关键字,也就是表头文本;另一个排序方向,升或者降。
Th: { css: "#active { color: #fff; } #active #arrow { opacity: 1; } #active #key { color: #fff; }\ #arrow { display: inline-block; vertical-align: middle; width: 0; height: 0; margin-left: 5px; opacity: 0.66; }\ #asc { border-left: 4px solid transparent; border-right: 4px solid transparent; border-bottom: 4px solid #fff;}\ #dsc { border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 4px solid #fff; }", xml: "<th id='th'>\ <span id='key'/><span id='arrow'/>\ </th>", fun: function (sys, items, opts) { var order = "#asc"; this.watch("sort", function (e, key, order) { sys.key.text().toLowerCase() == key || sys.th.removeClass("#active"); }); this.on("click", function (e) { sys.th.addClass("#active"); sys.arrow.removeClass(order); order = order == "#asc" ? "#dsc" : "#asc"; sys.arrow.addClass(order).notify("sort", [sys.key.text().toLowerCase(), order]); }); sys.arrow.addClass("#asc"); return { val: sys.key.text }; } }
设计表体
表体可以有多行,但表体只负责展示数据,所以实现起来比表头要简单的多。
Tbody: { xml: `<tbody id='tbody'/>`, fun: function (sys, items, opts) { function setValue(gridColumns, gridData) { sys.tbody.children().call("remove"); gridData.forEach(data => tr = sys.tbody.append("tr"); gridColumns.forEach(key => tr.append("td").text(data[key])); )); } return { val: setValue }; } }
加入排序功能
为了便于管理,我们把排序功能单独封装成一个组件,该组件提供一个排序接口,同时侦听一个排序消息。一旦接收到排序消息,则记录下关键字与排序方向,并派发一个表体刷新命令。
Sort: { fun: function (sys, items, opts) { var sortKey, sortOrder; this.watch("sort", function (e, key, order) { sortKey = key, sortOrder = order; this.trigger("update"); }); return function (data) { return sortKey ? data.slice().sort(function (a, b) { a = a[sortKey], b = b[sortKey]; return (a === b ? 0 : a > b ? 1 : -1) * (sortOrder == "#asc" ? 1 : -1); }) : data; }; } }
要完整地实现排序功能,对组件 DataGrid 作一些修正,主要是内置上述的排序功能组件并侦听表体刷新指令。一旦接收到刷新指令,则对表体数据完成排序并刷新表体。
DataGrid: { xml: `<table id='table'> <Thead id='thead'/> <Tbody id='tbody'/> <Sort id='sort'/> </table>`, fun: function (sys, items, opts) { var data = {gridColumns: [], gridData: []}; function setValue(value) { data = value; items.thead.val(data.gridColumns); items.tbody.val(data.gridColumns, data.gridData); } function filter(filterKey) { // 过滤函数 } this.on("update", function() { items.tbody.val(items.sort(data.gridData)); }); return { val: setValue, filter: filter }; } }
加入过滤功能
与排序功能的加入流程类似,我们把过滤功能单独封装成一个组件,该组件提供一个过滤接口,同时侦听一个过滤消息。一旦接收到消息,则记录下过滤关键字,并派发一个表体刷新命令。
Filter: { fun: function (sys, items, opts) { var filterKey = ""; this.watch("filter", function (e, key) { filterKey = key.toLowerCase(); this.trigger("update"); }); return function (data) { return data.filter(function (row) { return Object.keys(row).some(function (key) { return String(row[key]).toLowerCase().indexOf(filterKey) > -1; }); }); }; } }
另外需要对组件 DataGrid 作一些修正,修正内容与上述的排序功能的加入类似,区别在于额外完善了 filter 接口以及对消息作用域进行了限制。下面是我们最终的网格组件。
DataGrid: { css: `#table { border: 2px solid #42b983; border-radius: 3px; background-color: #fff; } #table th { background-color: #42b983; color: rgba(255,255,255,0.66); cursor: pointer; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } #table td { background-color: #f9f9f9; } #table th, #table td { min-width: 120px; padding: 10px 20px; }`, xml: `<table id='table'> <Thead id='thead'/> <Tbody id='tbody'/> <Sort id='sort'/> <Filter id='filter'/> </table>`, map: { msgscope: true }, fun: function (sys, items, opts) { var data = {gridColumns: [], gridData: []}; function setValue(value) { data = value; items.thead.val(data.gridColumns); items.tbody.val(data.gridColumns, data.gridData); } function filter(filterKey) { sys.table.notify("filter", filterKey); } this.on("update", function() { items.tbody.val(items.filter(items.sort(data.gridData))); }); return { val: setValue, filter: filter }; } }
值得注意的是这里一定要在映射项中配置限制消息作用域的选项。否则,当在一个应用中实例化多个网格组件时,消息就会互相干扰。
测试
最后我们来测试下我们完成的组件,测试的功能主要就是刚开始提到的三个:数据展示、排序以及过滤。
Index: { css: "#index { font-family: Helvetica Neue, Arial, sans-serif; font-size: 14px; color: #444; }\ #search { margin: 8px 0; }", xml: "<p id='index'>\ Search <input id='search'/>\ <Table id='table'/>\ </p>", fun: function (sys, items, opts) { items.table.val(data); sys.search.on("input", e => items.table.filter(sys.search.prop("value"))); } }
本系列文章基于 xmlplus 框架。如果你对 xmlplus 没有多少了解,可以访问 www.xmlplus.cn。这里有详尽的入门文档可供参考。
【相关推荐】
1. 免费js在线视频教程
3. php.cn独孤九贱(3)-JavaScript视频教程
以上是JavaScript框架(xmlplus)组件的介绍(十)网格(DataGrid)的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

本文讨论了在浏览器中优化JavaScript性能的策略,重点是减少执行时间并最大程度地减少对页面负载速度的影响。

本文讨论了使用浏览器开发人员工具的有效JavaScript调试,专注于设置断点,使用控制台和分析性能。

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

本文说明了如何使用源地图通过将其映射回原始代码来调试JAVASCRIPT。它讨论了启用源地图,设置断点以及使用Chrome DevTools和WebPack之类的工具。

本教程将介绍如何使用 Chart.js 创建饼图、环形图和气泡图。此前,我们已学习了 Chart.js 的四种图表类型:折线图和条形图(教程二),以及雷达图和极地区域图(教程三)。 创建饼图和环形图 饼图和环形图非常适合展示某个整体被划分为不同部分的比例。例如,可以使用饼图展示野生动物园中雄狮、雌狮和幼狮的百分比,或不同候选人在选举中获得的投票百分比。 饼图仅适用于比较单个参数或数据集。需要注意的是,饼图无法绘制值为零的实体,因为饼图中扇形的角度取决于数据点的数值大小。这意味着任何占比为零的实体

深入探讨console.log输出差异的根源本文将分析一段代码中console.log函数输出结果的差异,并解释其背后的原因。�...
