1. 程式人生 > >JS元件系列——自己動手封裝bootstrap-treegrid元件

JS元件系列——自己動手封裝bootstrap-treegrid元件

前言:最近產品需要設計一套相對完整的組織架構的解決方案,由於組織架構涉及到層級關係,在表格裡面展示層級關係,自然就要用到所謂的treegrid。可惜的是,一些輕量級的表格元件本身並沒有自帶樹形表格的功能,比如bootstrapTable就沒有這個功能,怎麼辦呢?如果是jqgrid、easyUI的表格,treegrid的效果可以說是輕而易舉就能解決,而專案目前用的就是bootstrapTable,不可能這個時候因為這個需求去換元件吧。博主分析了下,無非就兩種解決方案:一種就是擴充套件bootstrapTable的treegrid功能;第二種就是再找一個單獨的treegrid元件去實現這個功能。博主在網上找了下,找到了一個效果還不錯的treegrid第三方元件,於是做了下封裝,今天分享出來,供大家參考。

一、開源的treegrid

1、元件效果預覽

最原始的效果

 

bootstrap樣式的效果

這個是元件最原始的效果,後面會告訴大家博主做了哪些封裝以及加了哪些功能。

在此還是給出一個封裝過的效果吧!

2、元件開源地址

最後還是給出github上面一個開源的treegrid元件。

二、封裝treegrid

1、元件封裝的必要性

(1)縱觀元件的所有的demo和文件,基本都是說的我們直接寫死的table標籤,然後通過樣式去確定父子關係,最後初始化得到效果,但大部分情況下,我們的表格資料都不是寫死的,而是通過後臺獲取資料,然後將資料渲染到前端,最終得到我們想要的效果,如果根據元件目前的使用方式,我們得到一個集合資料之後,需要自己去拼接tr、td這些東西,這都是小事,最麻煩的是元件是有父子關係的,我們需要根據我們資料之間的關係轉化為元件的父子關係,並且由於支援無限級,還涉及到資料的遞迴運算。這個複雜的過程是我們不想經常去做的,怎麼辦呢?最好的思路就是封裝了,封裝的時候麻煩一次,以後使用就簡單了,可以說這是一件一勞永逸的事情。

(2)一般來說,既然是treegrid,肯定會有表頭,而這個表頭是根據資料來動態顯示的。元件自帶的效果可以自己寫死表頭,但還是那句話,使用的靈活性太差。

由於以上兩點,於是才有了今天的這篇文章。

2、元件封裝程式碼示例

首先我們將treegrid元件下載並引用到我們的專案裡面,然後向其目錄裡面加一個extension的資料夾,裡面新增一個jquery.treegrid.extension.js的檔案。

然後就是最重要的jquery.treegrid.extension.js檔案的內容:

(function ($) {
    "use strict";

    $.fn.treegridData 
= function (options, param) { //如果是呼叫方法 if (typeof options == 'string') { return $.fn.treegridData.methods[options](this, param); } //如果是初始化元件 options = $.extend({}, $.fn.treegridData.defaults, options || {}); var target = $(this); debugger; //得到根節點 target.getRootNodes = function (data) { var result = []; $.each(data, function (index, item) { if (!item[options.parentColumn]) { result.push(item); } }); return result; }; var j = 0; //遞迴獲取子節點並且設定子節點 target.getChildNodes = function (data, parentNode, parentIndex, tbody) { $.each(data, function (i, item) { if (item[options.parentColumn] == parentNode[options.id]) { var tr = $('<tr></tr>'); var nowParentIndex = (parentIndex + (j++) + 1); tr.addClass('treegrid-' + nowParentIndex); tr.addClass('treegrid-parent-' + parentIndex); $.each(options.columns, function (index, column) { var td = $('<td></td>'); td.text(item[column.field]); tr.append(td); }); tbody.append(tr); target.getChildNodes(data, item, nowParentIndex, tbody) } }); }; target.addClass('table'); if (options.striped) { target.addClass('table-striped'); } if (options.bordered) { target.addClass('table-bordered'); } if (options.url) { $.ajax({ type: options.type, url: options.url, data: options.ajaxParams, dataType: "JSON", success: function (data, textStatus, jqXHR) { debugger; //構造表頭 var thr = $('<tr></tr>'); $.each(options.columns, function (i, item) { var th = $('<th style="padding:10px;"></th>'); th.text(item.title); thr.append(th); }); var thead = $('<thead></thead>'); thead.append(thr); target.append(thead); //構造表體 var tbody = $('<tbody></tbody>'); var rootNode = target.getRootNodes(data); $.each(rootNode, function (i, item) { var tr = $('<tr></tr>'); tr.addClass('treegrid-' + (j + i)); $.each(options.columns, function (index, column) { var td = $('<td></td>'); td.text(item[column.field]); tr.append(td); }); tbody.append(tr); target.getChildNodes(data, item, (j + i), tbody); }); target.append(tbody); target.treegrid({ expanderExpandedClass: options.expanderExpandedClass, expanderCollapsedClass: options.expanderCollapsedClass }); if (!options.expandAll) { target.treegrid('collapseAll'); } } }); } else { //也可以通過defaults裡面的data屬性通過傳遞一個數據集合進來對元件進行初始化....有興趣可以自己實現,思路和上述類似 } return target; }; $.fn.treegridData.methods = { getAllNodes: function (target, data) { return target.treegrid('getAllNodes'); }, //元件的其他方法也可以進行類似封裝........ }; $.fn.treegridData.defaults = { id: 'Id', parentColumn: 'ParentId', data: [], //構造table的資料集合 type: "GET", //請求資料的ajax型別 url: null, //請求資料的ajax的url ajaxParams: {}, //請求資料的ajax的data屬性 expandColumn: null,//在哪一列上面顯示展開按鈕 expandAll: true, //是否全部展開 striped: false, //是否各行漸變色 bordered: false, //是否顯示邊框 columns: [], expanderExpandedClass: 'glyphicon glyphicon-chevron-down',//展開的按鈕的圖示 expanderCollapsedClass: 'glyphicon glyphicon-chevron-right'//縮起的按鈕的圖示 }; })(jQuery);

程式碼說明

1、為了避免和源元件的初始化衝突,我們自定義的元件取了一個別名,叫 treegridData 。我們使用元件的時候就通過treegridData來進行初始化,如果你覺得這個名稱不順眼,可以自行修改。

3、defaults裡面就是初始化元件的時候可以傳遞的引數,上述註釋基本上寫得比較清楚。id和parentId兩個引數主要是用來描述資料之間的父子級關係,後面我們介紹元件時候的時候你一看就能明白。

4、博主加了幾個自認為很有用的屬性和方法,應該能減少一些使用的麻煩。比如初始化元件的時候是否展開所有的子節點、新增title、表格行的漸變色和表格邊框等。

5、上述封裝裡面遞迴查詢子節點的時候,每一次都需要遍歷所有的資料去找子節點,效率偏低,如果你使用了類似linq to js之類的元件去操作js的集合,可以優化那部分程式碼,適當提高遞迴的效率。當然,如果你的結果集本身資料量不太大,這麼寫影響也不太大。

3、封裝後的元件使用

我們在介面上面引用需要的css和js檔案

   <link href="~/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
    <link href="~/Content/jquery-treegrid-master/css/jquery.treegrid.css" rel="stylesheet" />

   <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Content/bootstrap/js/bootstrap.min.js"></script>
    <script src="~/Content/jquery-treegrid-master/js/jquery.treegrid.min.js"></script>
    <script src="~/Content/jquery-treegrid-master/js/jquery.treegrid.bootstrap3.js"></script>
    <script src="~/Content/jquery-treegrid-master/extension/jquery.treegrid.extension.js"></script>

然後定義一個空的table標籤

<table id="tb" ></table>

最後就是js初始化了

$(document).ready(function () {
            $('#tb').treegridData({
                id: 'Id',
                parentColumn: 'ParentId',
                type: "GET", //請求資料的ajax型別
                url: '/TestMVC/GetData',   //請求資料的ajax的url
                ajaxParams: {}, //請求資料的ajax的data屬性
                expandColumn: null,//在哪一列上面顯示展開按鈕
                striped: true,   //是否各行漸變色
                bordered: true,  //是否顯示邊框
                //expandAll: false,  //是否全部展開
                columns: [
                    {
                        title: '機構名稱',
                        field: 'Name'
                    },
                    {
                        title: '機構描述',
                        field: 'Desc'
                    }
                ]
            });
        });

當然啦,還得配上後臺的取資料的方法

  public class TestMVCController : Controller
    {public JsonResult GetData()
        {
            var result = new List<object>();
            result.Add(new { Id = 1, Name = "百度科技", Desc = "搜尋巨頭"});
            result.Add(new { Id = 2, Name = "百度事業部", Desc = "搜尋巨頭",ParentId=1 });
            result.Add(new { Id = 3, Name = "百度人事部", Desc = "搜尋巨頭", ParentId = 1 });
            result.Add(new { Id = 11, Name = "百度HH部", Desc = "搜尋巨頭", ParentId = 2 });
            result.Add(new { Id = 4, Name = "百度行政", Desc = "搜尋巨頭", ParentId = 1 });
            result.Add(new { Id = 5, Name = "百度YY部", Desc = "搜尋巨頭", ParentId = 1 });
            result.Add(new { Id = 12, Name = "百度BB部", Desc = "搜尋巨頭", ParentId = 2 });
            result.Add(new { Id = 6, Name = "搜狐科技", Desc = "IT" });
            result.Add(new { Id = 7, Name = "搜狐資訊部", Desc = "IT", ParentId = 6 });
            result.Add(new { Id = 8, Name = "搜狐人事", Desc = "IT", ParentId = 6 });
            result.Add(new { Id = 9, Name = "搜狐事業部", Desc = "IT", ParentId = 6 });
            result.Add(new { Id = 10, Name = "搜狐事業子部", Desc = "IT", ParentId = 9 });
            return Json(result, JsonRequestBehavior.AllowGet);
        }
    }

這裡一看應該就能明白元件defaults裡面的id和parentColumn的作用了吧。記得jqgrid裡面使用treeview的時候用到了一個level用來判斷是哪一級別的節點,博主覺得這樣硬性要求返回資料裡面加一個level屬性有點不妥,所以我們約定如果當前記錄的parentId為null或者空字串的時候,這個節點就是根節點,然後根據根節點去遞迴找子節點。

使用後的各種效果示例如下。

初始化的時候配置expandAll: false得到的效果

增加隔行變色striped: true

增加表格邊框bordered: true

綜合效果

三、總結

至此本文就結束了,沒有什麼太高大上的技術,就是簡單將一個第三方元件進行了一些封裝,使得其使用起來更加方便而已。如果你專案中也正在為treegrid而糾結,何不試試呢。其實擴充套件bootstrapTable的treegrid功能的思路博主已經有了,等有時間在下篇給出說明。

如果你覺得本文能夠幫助你,可以右邊隨意 打賞 博主,也可以 推薦 進行精神鼓勵。你的支援是博主繼續堅持的不懈動力。

歡迎各位轉載,但是未經作者本人同意,轉載文章之後必須在文章頁面明顯位置給出作者和原文連線,否則保留追究法律責任的權利

相關推薦

JS元件系列——自己動手封裝bootstrap-treegrid元件

前言:最近產品需要設計一套相對完整的組織架構的解決方案,由於組織架構涉及到層級關係,在表格裡面展示層級關係,自然就要用到所謂的treegrid。可惜的是,一些輕量級的表格元件本身並沒有自帶樹形表格的功能,比如bootstrapTable就沒有這個功能,怎麼辦呢?如果是jqgrid、easyUI的表格,tree

JS元件系列——自己動手擴充套件BootstrapTable的treegrid功能

前言:上篇  JS元件系列——自己動手封裝bootstrap-treegrid元件 博主自己動手封裝了下treegrid的功能,但畢竟那個元件只是一個單獨針對樹形表格做的,適用性還比較有限。關注博主的園友應該知道,博主的部落格裡面寫了很多bootstrapTable的擴充套件,今天打算在直接在bootstra

JS元件系列——自己動手擴充套件BootstrapTable的 凍結列 功能:徹底解決高度問題

前言:一年前,博主分享過一篇關於bootstrapTable元件凍結列的解決方案  JS元件系列——Bootstrap Table 凍結列功能IE瀏覽器相容性問題解決方案 ,通過該篇,確實可以實現bootstrapTable的凍結列效果,並且可以相容ie瀏覽器。這一年的時間,不斷有園友以及群裡面的朋友問過我關

自己動手封裝VxWorks下C++基礎類

VxWorks下采用C++構建Application可以使得程式更加利於維護,利用其提供的STL支援,可以省去大量的底層工作,大大加速軟體的開發進度。 Tornado完全支援C++開發,風河也提供了包括STL在內的豐富的C++元件,但由於VxWorks的系統呼叫是以C函式的形

Android自定義控制元件系列一:如何測量控制元件尺寸

測量控制元件尺寸(寬度、高度)是開發自定義控制元件的第一步,只有確定尺寸後才能開始畫(利用canvas在畫布上畫,我們所使用的控制元件實際上都是這樣畫上去的)。當然,這個尺寸是需要根據控制元件的各個部分計算出來的,比如:padding、文字大小,間距等。非容器控制元件的onM

JS元件系列——分享自己封裝Bootstrap樹形元件:jqTree

 前言:之前的一篇介紹了下如何封裝自己的元件,這篇再次來體驗下自己封裝元件的樂趣。看過博主部落格的園友應該記得之前分享過一篇樹形選單的使用JS元件系列——Bootstrap 樹控制元件使用經驗分享,這篇裡面第一個Jquery Tree,只是用簡單樣式和js去實現了效果,沒有給出一個系統的封裝,這篇博主就來試試

JS元件系列——封裝自己JS元件,你也可以

前言:之前分享了那麼多bootstrap元件的使用經驗,這篇博主打算研究下JS元件的擴充套件和封裝,我們來感受下JQuery為我們提供$.Extend的神奇,看看我們怎麼自定義自己的元件,比如我們想擴充套件一個$("#id").MyJsControl({})做我們自己的元件,我們該如何去做呢,別急,我們慢慢來

JS元件系列——兩種bootstrap multiselect元件大比拼[轉載]

轉載原文地址:https://www.cnblogs.com/landeanfen/p/5013452.html 前言:今天繼續來看看bootstrap的另一個元件:multiselect。記得在專案開始之前,博主專案組幾個同事就使用哪些js元件展開過討論,其中就說到了select元件,

JS元件系列——表格元件神器:bootstrap table(三:終結篇,最後的乾貨福利)

前言:前面介紹了兩篇關於bootstrap table的基礎用法,這章我們繼續來看看它比較常用的一些功能,來個終結篇吧,毛爺爺告訴我們做事要有始有終~~bootstrap table這東西要想所有功能覆蓋似乎不太現實,博主挑選了一些自認為比較常用的功能在此分享給各位園友。原始

JS元件系列——表格元件神器:bootstrap table

前言:之前一直在忙著各種什麼效果,殊不知最基礎的Bootstrap Table用法都沒有涉及,罪過,罪過。今天補起來吧。上午博主由零開始自己從頭到尾使用了一遍Bootstrap Table ,遇到不少使用方面的問題,也做了一部分筆記,在此分享出來供需要使用的園友參考。還記得前

JS元件系列——表格元件神器:bootstrap table(二:父子表和行列調序)

前言:上篇 JS元件系列——表格元件神器:bootstrap table 簡單介紹了下Bootstrap Table的基礎用法,沒想到討論還挺熱烈的。有園友在評論中提到了父子表的用法,今天就結合Bootstrap table的父子表和行列調序的用法再來介紹下它稍微高階點的用法

JS元件系列——又一款MVVM元件:Vue(二:構建自己的Vue元件

前言:轉眼距離上篇 JS元件系列——又一款MVVM元件:Vue(一:30分鐘搞定前端增刪改查) 已有好幾個月了,今天打算將它撿起來,發現好久不用,Vue相關技術點都生疏不少。經過這幾個月的時間,Vue的發展也是異常迅猛,不過這好像和博主都沒什麼太大的關係,博主還是老老實實研究自己的技術吧。技術之路還很長,且行

JS元件系列——不容錯過的兩款Bootstrap Icon圖示選擇元件

前言:最近好多朋友在群裡面聊到bootstrap icon圖示的問題,比如最常見的選單管理,每個選單肯定需要一個對應的選單圖示,要是有一個視覺化的圖示選擇元件就好了,最好是直接選擇圖示,就能得到對應的class樣式。於是乎各種百度,皇天不負有心人,最後被博主找到了,感覺效果還不錯,並且支援自定義的圖示,今天就

JS元件系列——再推薦一款好用的bootstrap-select元件,親測還不錯

前言:之前分享過兩篇bootstrap下拉框的元件:JS元件系列——兩種bootstrap multiselect元件大比拼  和 JS元件系列——Bootstrap Select2元件使用小結 ,收到很多園友的關注和提問,最後總結這兩篇裡面的下拉框元件都存在一些大大小小的問題,比如兩種bootstrap m

JS元件系列——基於Bootstrap Ace模板的選單和Tab頁效果分享(你值得擁有)

前言:最近園子裡多了許多談語言、談環境、談逼格(格局)的文章,看看笑笑過後,殊不知其實都是然並卵。提升自己的技術才是王道。之前博主分享過多篇bootstrap元件的文章,引起了很多園友的關注和支援,看樣子這種風格還是受到很多園友青睞的。本著不辜負園友們的支援的原則,應群友們的要求,今天來分享下專案中使用Ace

JS元件系列——Bootstrap Table 表格行拖拽

前言:之前一直在研究DDD相關知識,好久沒更新JS系列文章了。這兩天做了一個簡單的業務需求,覺得效果還可以,今天在這裡分享給大家,歡迎拍磚~~ 一、業務需求及實現效果 專案涉及到訂單模組,那天突然接到一個需求,說是兩種不同狀態的訂單之間要實現插單的效果,頁面上呈現方式是:左右兩個Table,左邊Table

JS元件系列——Bootstrap右鍵選單解決方案:ContextMenu

前言:有段時間沒發表隨筆了,過個年人都變得懶了。新年剛來上班,今天正好得空,將去年遺留的兩個小元件總結記錄下。有朋友跟我說:你的bootstrap元件要能夠形成一個可以滿足一般專案需求的系列元件,才有真正的實用價值。想想說得在理。這不今天來總結下bootstrap的一個小元件的應用。好了,不說廢話,進入正題吧

JS元件系列——Bootstrap 樹控制元件使用經驗分享

前言:很多時候我們在專案中需要用到樹,有些樹僅僅是展示層級關係,有些樹是為了展示和編輯層級關係,還有些樹是為了選中項然後其他地方呼叫選中項。不管怎麼樣,樹控制元件都是很多專案裡面不可或缺的元件之一。今天,博主打算結合自己的使用經歷和網上找到的一些不錯的樹控制元件在這裡做一個分享,希望能幫大家找到最合適的控制元

JS元件系列——Bootstrap元件福利篇:幾款好用的元件推薦

前言:之前分享過很多bootstrap常用元件,包括表格、表單驗證、檔案上傳、複選下拉框、彈出框等。這段時間,博主又收藏了一些好用的元件(有些在專案中已經用起來了),經過兩天的時間,已經整理出了一部分,本著“好東西要與人分享”的原則,今天還是來點福利,將博主收藏的東西分享出來,供需要的園友參考。元件大部分都是

JS元件系列——在ABP中封裝BootstrapTable

 前言:關於ABP框架,博主關注差不多有兩年了吧,一直遲遲沒有嘗試。一方面博主覺得像這種複雜的開發框架肯定有它的過人之處,系統的穩定性和健壯性比一般的開源框架肯定強很多,可是另一方面每每想到它繁瑣的封裝和複雜的開發流程就望而卻步,就這樣遲遲沒有行動。最近在專案裡面用到了ABP框架,沒辦法,只有硬著頭皮上了。經