首頁 > web前端 > js教程 > 主體

JavaScript框架(xmlplus)元件的介紹(十)網格(DataGrid)

零下一度
發布: 2017-05-06 15:29:26
原創
1534 人瀏覽過

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=&#39;table&#39;>
  <Thead id=&#39;thead&#39;/>
  <Tbody id=&#39;tbody&#39;/>
  </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=&#39;thead&#39;>
  <tr id=&#39;tr&#39;/>
  </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=&#39;th&#39;>\
  <span id=&#39;key&#39;/><span id=&#39;arrow&#39;/>\
  </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=&#39;tbody&#39;/>`,
 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=&#39;table&#39;>
  <Thead id=&#39;thead&#39;/>
  <Tbody id=&#39;tbody&#39;/>
  <Sort id=&#39;sort&#39;/>
  </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=&#39;table&#39;>
  <Thead id=&#39;thead&#39;/>
  <Tbody id=&#39;tbody&#39;/>
  <Sort id=&#39;sort&#39;/>
  <Filter id=&#39;filter&#39;/>
  </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=&#39;index&#39;>\
  Search <input id=&#39;search&#39;/>\
  <Table id=&#39;table&#39;/>\
  </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線上影片教學

2. JavaScript中文參考手冊

3. php.cn獨孤九賤(3)-JavaScript影片教學

#

以上是JavaScript框架(xmlplus)元件的介紹(十)網格(DataGrid)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!