1. 程式人生 > >實戰:使用jqGrid實現非同步樹形列表

實戰:使用jqGrid實現非同步樹形列表

今天教大家使用jqGrid來實現非同步載入的樹形列表

先上效果圖:

非同步載入即不一次性的將所有的資料載入到頁面上,只有當需要的時候點選三角按鈕,才會將其子類載入到頁面上顯示,若其下無子類,則是圓圈標識。

下面是實現的步驟:

1.下載並引用必要的檔案

這個就不詳細講了,網上有許多教程。

2.前端頁面

一個table

一段JS

var jqGrid;
$(function() {
	var width = $(".lz-card-body").width() - 20;
	jqGrid = jQuery('#tree').jqGrid({
        //
		"url" : "/IssueConfig/findByPIdAndLevel",
		"datatype" : "json",
		"colModel" : [ {
			"name" : "issConfigId",
			"index" : "issConfigId",
			"sorttype" : "int",
			"key" : true,
			"hidden" : true
		}, {
			"name" : "descCn",
			"label" : "中文名稱",
			"sortable" : false,
			 /* formatter : function(cellvalue, options, rowObject) {
				var viewUrl = "/sysMenu/toView/" + rowObject.id;
				var html = "<a href='" + viewUrl;
				html += "' target=_blank>";
				html += cellvalue;
				html += "</a>";
				return html;
			}  */
		}, {
			"name" : "descEn",
			"label" : "英文名稱",
			"sortable" : false
		}, {
			"name" : "issCode",
			"label" : "序號",
			"sortable" : false,
			"align" : "center"
		}, {
			"name" : "issHelp",
			"label" : "問題幫助",
			"sortable" : false,
			"align" : "center"
		}, {
			"name" : "sort",
			"label" : "排序",
			"sortable" : false,
			"align" : "center",
			/* formatter : function(cellvalue, options, rowObject) {
				if(cellvalue){
					return cellvalue.labelCn;
				}
				return '';
			} */
		},  {
			"name" : "operation",
			"label" : "操作",
			"sortable" : false,
			"width" : 100,
			"align" : "center",
			formatter : function(cellvalue, options, rowObject) {
				var id = rowObject.issConfigId;
				var addUrl = "/IssueConfig/toAdd/" + id;
				var editUrl = "/IssueConfig/toEdit/" + id;
				var html = "<a href='" + addUrl;
				html += "' target=_blank title='add'>";
				html += "<i class='fa fa-plus'></i></a>&nbsp;&nbsp;";
				html += "<a href='" + editUrl;
				html += "' target=_blank title='edit'>";
				html += "<i class='far fa-edit'></i></a>";
				html += "&nbsp;&nbsp;<a href='#' title='delete' onclick=deleteMenu(";
				html += id;
				html += ")><i class='fa fa-trash'></i></a>";
				return html;
			}
		}, {
			"name" : "parentId",
			"hidden" : true
		}, {
			"name" : "level",
			"hidden" : true
		}, {
			"name" : "isLeaf",
			"hidden" : true
		}, {
			"name" : "expanded",
			"hidden" : true
		}, {
			"name" : "loaded",
			"hidden" : true
		} ],
		"width" : width,
		"hoverrows" : false,
		"viewrecords" : false,
		"gridview" : true,
		"height" : "auto",
		"sortname" : "issConfigId",
		"sortable" : false,
		"scrollrows" : true,
		"tree_root_level" : 0,
		"treeGrid" : true,
		"ExpandColumn" : "descCn",
		"treedatatype" : "json",
		"treeGridModel" : "adjacency",
		"loadonce" : false,
		"rowNum" : 100,
		"treeReader" : {
			"parent_id_field" : "parentId",
			"level_field" : "level",
			"leaf_field" : "isLeaf",
			"expanded_field" : "expanded",
			"loaded" : "loaded",
			"icon_field" : "icon1"
		}
	});
});

哎.....寫的草稿沒儲存,不想在寫一遍了

說一下重要的引數吧

tree_root_level" : 0,
      "treeGrid" : true,
        "ExpandColumn" : "descCn",
        "treedatatype" : "json",
        "treeGridModel" : "adjacency",
        "loadonce" : false,

下面的是詳細的api文件,不是太難

https://blog.csdn.net/yjlwl1213/article/details/41750703

3.後臺程式碼

首先要知道,因為是弄清楚前臺需要給後臺什麼引數,後臺返給前臺的資料結構是什麼樣子。

1.前臺給後臺

因為是非同步載入,點選父節點才加載出其直接子節點,那麼肯定要發回parent id,然後每一層 它的Level都要加1,所以要把父節點的level發回。

/**
	 * 根據parent_id和level查詢選單(非同步載入)
	 * 
	 * @param parentId
	 * @param level
	 * @return
	 */
	@RequestMapping(value = "/findByPIdAndLevel", method = RequestMethod.GET)
	@ResponseBody
	public List<IssueConfigVo> findByPIdAndLevel() {
        //獲得父節點和父節點的level
		String nodeId = request.getParameter("nodeid");
		String n_level = request.getParameter("n_level");
        //null的話即為最開始載入的level=0的根節點
		Long parentId = StringUtils.isEmpty(nodeId) ? null : Long.parseLong(nodeId);
		Integer level = StringUtils.isEmpty(n_level) ? null : Integer.parseInt(n_level);
		return issueConfigService.getMenusTree(parentId, level);
	}

2.搞清楚要返回的資料結構,怎麼樣才能被前臺識別形成樹結構

//返回的類
public class IssueConfigVo extends IssueConfig {
	private static final long serialVersionUID = 1L;

	private Long id;
    //父節點 id 其實這邊不需要也可以,因為基礎類裡面就已經有parent 欄位了,只需要在Js中設定一下
	private Long parent;
	private Integer level = 0;
	private boolean isLeaf;
	private boolean loaded = false;
	private boolean expanded = true;
    //資料
	private IssueConfig father;
}
//實體類
@Entity
@Table(name = "NT_T_ISSUE_CONFIG")
public class IssueConfig extends BaseEntity {
	private static final long serialVersionUID = 1L;

	// 主鍵
	private Long issConfigId;

	// 建立時間
	private Date createDate;

	// 建立人ID
	private String createUserid;

	// 建立人
	private String createUsername;

	// 中文描述
	private String descCn;

	// 英文描述
	private String descEn;

	// 問題序號
	private String issCode;

	// 問題幫助
	private String issHelp;

	// 修改時間
	private Date modifyDate;

	// 修改人員ID
	private String modifyUserid;

	// 上次節點
	private Long parentId;

	// 問題排序
	private Integer sort;

	// 狀態
	private String status;
}

3.遞迴獲取List

/**
	 * 遞迴選單
	 * 
	 * @param param
	 * @return
	 */
	public List<IssueConfigVo> getMenusTree(Long pid, Integer level) {
		List<IssueConfigVo> issueConfigVoList = new ArrayList<IssueConfigVo>();
        //根據父節點id,找到其直接子節點
		List<IssueConfigVo> issueConfigVo = IssueConfigVo
				.setList(findByParentId(pid));
        //設定level,因為我這邊的業務需求,只有兩層,如果需要多層,使用level +=1遞增
		if (level == null) {
			level = 0;
		} else {
			level = 1;
		}

		if (issueConfigVo != null && !issueConfigVo.isEmpty()) {
			for (IssueConfigVo menuVo : issueConfigVo) {
                //設定子節點屬性
				menuVo.setLevel(level);
                //這邊是因為剛寫的時候不瞭解,遞迴獲取了子節點,其實是不需要的,
                //因為實體類中有parent欄位,我們只需要設定好parentId,並在前端
                //js裡面設定好,jqgrid就能將樹拼接好
				/*List<IssueConfigVo> children = getMenusTree(menuVo
						.getIssConfigId());*/
				if (children.isEmpty()) {
					menuVo.setIsLeaf(true);
				} else {
					menuVo.setIsLeaf(false);
				}
				// menuVo.setChildren(children);
                //設定parentId,一定要設定
				menuVo.setParent(menuVo.getParentId());
				issueConfigVoList.add(menuVo);
			}
		}
		return issueConfigVoList;
	}
//下面是遞迴獲取子節點,有興趣的人可以看一下,其實不需要
    /**
	 * 遞迴選單
	 * 
	 * @param param
	 * @return
	 */
	public List<IssueConfigVo> getMenusTree(Long pid) {
		List<IssueConfigVo> issueConfigVoList = new ArrayList<IssueConfigVo>();
		List<IssueConfigVo> issueConfigVo = IssueConfigVo
				.setList(findByParentId(pid));

		if (issueConfigVo != null && !issueConfigVo.isEmpty()) {
			for (IssueConfigVo menuVo : issueConfigVo) {
				menuVo.setChildren(getMenusTree(menuVo.getIssConfigId()));
				issueConfigVoList.add(menuVo);
			}
		}
		return issueConfigVoList;
	}

然後樹就完成啦!最後,其實js裡面也不需要那麼麻煩,因為也是第一次寫所以不熟悉,下面是精簡班,主要功能不變,後臺程式碼也不需要變動

jQuery(grid_selector).jqGrid({
		treeGrid : true,
		width : width,
		treeGridModel : "adjacency",
		ExpandColumn : "descCn",
		ExpandColClick : false,
		url : "/IssueConfig/findByPIdAndLevel",
		datatype : "json",
		colModel : [ {
			name : "issConfigId",
			index : "issConfigId",
			key : true,
			hidden : true, 
			 formatter : function(cellvalue, options, rowObject) {
				var rowId = rowObject.issConfigId;
				var checkbox = '<input type="hidden" name=""';
				checkbox += 'value="';	
				checkbox += rowId
				checkbox += '"/>';
				return checkbox;
			} 
		}, {
			label : nameFormat,
			name : "descCn",
			index : "descCn",
			formatter : function(cellvalue, options, rowObject) {
				index++;
				var rowId = rowObject.issConfigId;
				var descCn = rowObject.descCn;
				var checkbox = '<input type="checkbox" id="chx';
				checkbox += rowId;
				checkbox += '" value="';
				checkbox += descCn;
				checkbox += '" onclick="clickCheckbox(';
				checkbox += rowId;
				checkbox += ', this);"';
				checkbox += 'name=""';
				checkbox += ' />';
				checkbox += rowObject.descCn;
				return checkbox;
			} 
		}, {
			label : "英文名稱",
			name : "descEn",
			index : "descEn",
			formatter : function(cellvalue, options, rowObject) {
				var descEn = rowObject.descEn;
				var checkbox = '<input type="hidden" ';
				checkbox += ' name="" value="';
				checkbox += descEn;
				checkbox += '"/>';
				checkbox += rowObject.descEn;
				return checkbox;
			}
		} ,{
			name : "issCode",
			hidden : true,
			formatter : function(cellvalue, options, rowObject) {
				var issCode = rowObject.issCode;
				var checkbox = '<input type="hidden" name=""';
				checkbox += 'value="';	
				checkbox += issCode
				checkbox += '"/>';
				return checkbox;
			}
		}, {
			name : "sort",
			hidden : true,
			formatter : function(cellvalue, options, rowObject) {
				var sort = rowObject.sort;
				var checkbox = '<input type="hidden" name=""';
				checkbox += 'value="';	
				checkbox += sort
				checkbox += '"/>';
				return checkbox;
		} 
		},{
			name : "parentId",
			hidden : true,
			formatter : function(cellvalue, options, rowObject) {
					var parentId = rowObject.parentId;
					var checkbox = '<input type="hidden" name=""';
					checkbox += 'value="';	
					checkbox += parentId
					checkbox += '"/>';
					return checkbox;
			} 
		} ],
		page : false,
		rowNum: 100,
		loadonce : false,
		tree_root_level : 0,
		gridview : true, 
		height : "auto"
	});

有問題可以交流