国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

xmlplus組件設計系列之網格(DataGrid)(10)

2019-11-19 16:39:47
字體:
來源:轉載
供稿:網友

這一章我們要實現是一個網格組件,該組件除了最基本的數據展示功能外,還提供排序以及數據過濾功能。

數據源

為了測試我們即將編寫好網格組件,我們采用如下格式的數據源。此數據源包含兩部分的內容,分別是表頭數據集和表體數據集。網格組件實例最終的列數由表頭數據集的長度決定。

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: "<div id='index'>/  Search <input id='search'/>/  <Table id='table'/>/  </div>", 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。這里有詳盡的入門文檔可供參考。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 玉山县| 南川市| 睢宁县| 宁蒗| 镶黄旗| 西华县| 双牌县| 太白县| 涞源县| 大同市| 南宫市| 淳化县| 西和县| 色达县| 云霄县| 常山县| 隆子县| 来凤县| 治县。| 阳谷县| 桂平市| 临汾市| 阳原县| 友谊县| 奉化市| 洪泽县| 陆良县| 襄城县| 保靖县| 巩义市| 五莲县| 怀化市| 皋兰县| 库尔勒市| 永康市| 从江县| 惠州市| 鹰潭市| 南城县| 珲春市| 喀喇沁旗|