載layui.css layui.js以后需要注意以下方面:
1、所有的radio checkbox要改變樣式的都要放到form 里邊;
2、form 要加上 class="layui-form"
3、復選框有兩種顯示方式
圖1 復選框顯示方式1
圖2 復選框顯示方式2
第一種:<input type="checkbox" title='顯示' checked />
第二種:<input type="checkbox" title='顯示' checked lay-skin="primary"/>
比較會發現 第二種只是多了一個選擇 lay-skin="primary"
4、在</form>以后要加上
<script>
layui.use('form', function(){
var form=layui.form;
})
</script>
我是加到了頁面底部,對form內的樣式渲染
5、鼠標監聽事件 form內的select button 等
select 觸發 通常用在調用下級分類
button 會提交信息 可以實現ajax提交數據
事實上不管哪種觸發都需要用到 lay-filter
<script>
layui.use('form', function(){
var form=layui.form;
form.on('select(myselect)', function(data){
這是select觸發的事件 <select lay-filter="myselect">
data.value 就是獲取到的option的value
});
form.on('submit(btnsub)', function(data){
這是button觸發的事件 <button lay-submit lay-filter="btnsub">
只是多了一個lay-submit
});
})
如果用到ajax獲取下級分類以后,比如select ,要在完成以后加上form.render(); 重新渲染 ;
通過ajax提交數據,需要先獲取到form表單的數據,parms=$("#formact").serialize();formact是form的ID;但是這樣獲取不到圖片上傳選擇圖片的數據,這就需要我們先上傳圖片,把圖片地址賦值到input里邊,建議圖片上傳先通過ajax 或者iframe上傳圖片;
</script>
這些可以和jquery nude.js等等交叉使用,不必拘泥一個思路。
css calc的用法
calc是頁面布局會經常用到,比如想讓頁面兩邊空出來10個像素;通過width:calc(100% - 20px); 設置居中,就輕易實現了兩邊空白10px,需要注意的是 100% 和 - 以及后邊的20px是有空格的
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>柵格系統</title>
<!--LayUI的核心css文件-->
<link rel="stylesheet" type="text/css" href="layui/css/layui.css"/>
<!--LayUI的核心js文件-->
<script src="layui/layui.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!--
柵格系統
列組合
1.定義行 .layui-row
2.定義列 .layui-col-md*
md 表示不同屏幕的標識(xs sm md lg)
* 表示列數量
3.每一行均分為12列,列的總數不能超過12,否則會自動換行
4.響應式規則
柵格會自動根據屏幕分辨率選擇對應的樣式效果
列邊距
.layui-col-space*
* 代表的式px值(1~30)
列偏移
將列向右移動指定列數
.layui-col-md-offset*
* 代表的是列數
列嵌套
列之間可以無限嵌套列
-------------------------------------------------------------------------
|超小屏幕 |小屏幕 |中等屏幕 |大型屏幕
|(手機<768px) |(平板>=768px) |(桌面>=992px) |(桌面>=1200px)
--------------------------------------------------------------------------
.layui- |auto |750px |970px |1170px
container |
的值 |
--------------------------------------------------------------------------
標記 |xs |sm |md |lg
--------------------------------------------------------------------------
列對應類* |layui-col-xs* |layui-col-sm*|layui-col-md* |layui-col-lg*
為1-12的 |
等分的值 |
--------------------------------------------------------------------------
總列數 |12 |12 |12 |12
--------------------------------------------------------------------------
響應行為 |始終按設定的比 |在當前屏幕下水 |在當前屏幕下水平|在當前屏幕下水平
|例水平排列 |平排列,如果屏 |排列,如果屏幕大|排列,如果屏幕大
| |幕大小低于臨界 |小低于臨界則堆疊|小低于臨界則堆疊
| |則堆疊排列 | 排列 |排列
--------------------------------------------------------------------------
-->
<!--布局容器-->
<div class="layui-container">
<!--定義行-->
<div class="layui-row">
<!--定義列-->
<div class="layui-col-md5" style="background-color: rgb(130, 215, 243);">
內容5/12
</div>
<div class="layui-col-md7" style="background-color: rgb(44, 141, 173);">
內容7/12
</div>
</div>
<!--定義行-->
<div class="layui-row">
<!--定義列-->
<div class="layui-col-md4" style="background-color: rgb(6, 126, 18);">
內容4/12
</div>
<div class="layui-col-md4" style="background-color: rgb(116, 180, 122);">
內容4/12
</div>
</div>
</div>
<hr>
<h3>平板、桌面端的不同表現:</h3>
<div class="layui-row">
<div class="layui-col-sm6 layui-col-md4" style="background-color:thistle">
平板>=768px:6/12 | 桌面>=992px: 4/12
</div>
</div>
<div class="layui-row">
<div class="layui-col-sm4 layui-col-md6" style="background-color: rgb(28, 104, 107);">
平板>=768px:4/12 | 桌面>=992px: 6/12
</div>
</div>
<div class="layui-row">
<div class="layui-col-sm12 layui-col-md8" style="background-color: rgb(201, 32, 130);">
平板>=768px:12/12 | 桌面>=992px: 8/12
</div>
</div>
<hr>
<h3>列邊距</h3>
<div class="layui-row layui-col-space10">
<div class="layui-col-md4" >
<div style="background-color:rgb(189, 139, 247)">4</div>
</div>
<div class="layui-col-md4" >
<div style="background-color:rgb(134, 39, 197)">5</div>
</div>
<div class="layui-col-md4" >
<div style="background-color:rgb(116, 19, 243)">6</div>
</div>
</div>
<hr>
<h3>列偏移</h3>
<div class="layui-row">
<div class="layui-col-md4" >
<div style="background-color:rgb(247, 240, 139)">4</div>
</div>
<div class="layui-col-md4 layui-col-md-offset4" >
<div style="background-color:rgb(163, 180, 6)">向右移動4個位置</div>
</div>
</div>
<hr>
<h3>列嵌套</h3>
<div class="layui-row">
<div class="layui-col-md6" >
<div style="background-color:rgb(247, 240, 139)">
<div class="layui-row">
<div class="layui-col-md3" style="background-color:rgb(248, 149, 118)">內部列</div>
<div class="layui-col-md5" style="background-color:rgb(207, 250, 166)">內部列</div>
<div class="layui-col-md4" style="background-color:rgb(133, 248, 181)">內部列</div>
</div>
</div>
</div>
</div>
</body>
</html>
現Tree樹的插件很多,比如常見的UI:Layui、ElementUI、iView ... 。這里我們介紹一個小巧的構建Tree樹的插件 zTree.js
zTree.js 官網API介紹的灰常詳細了,這里我們實戰使用zTree.js構建一棵Tree樹。
<!--more-->
寫在前面 下列文章中講述的實例,需要使用的后端數據是已經查詢好的,這里我們不講怎么查詢數據,只講如何使用現有的數據構建Tree樹,詳細的教程請查看我的 GitHub, 如果你覺得寫得好,歡迎star呀?。?/p>
使用zTree.js首先需要導入zTree的依賴庫文件,傳送門。
由于我使用了基于boostrap主題的zTree,所以還是建議大家去我的GitHub項目地址下載(CSS是修改過的),傳送門:GitHub
頁面中需要引入如下依賴庫文件:
<link rel="stylesheet" href="static/lib/bootstrap.min.css"/> <link rel="stylesheet" href="static/lib/css/demo.css"/> <link rel="stylesheet" href="static/lib/css/metroStyle/metroStyle.css"/> <script type="text/javascript" src="static/lib/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="static/lib/jquery.ztree.core.min.js"></script> <script type="text/javascript" src="static/lib/jquery.ztree.excheck.min.js"></script>
<!--more-->
查閱zTree.js官網API,構建一棵Tree樹很簡單:
一、前端初始化一個div,用來展示Tree樹
zTree構建的Tree樹是用iframe嵌套的,所以不用擔心寬度、高度的問題
<div class="zTreeDemoBackground"> <ul id="tree" class="ztree"></ul> </div>
初始化的div只需要關注id屬性即可,因為JS中會根據這個ID找到構建Tree樹的位置。
二、javaScript加載Tree樹
為了真實點構建Tree樹,我這里用一個json文件來模擬請求后端的數據。在同級目錄下創建data.json,在其中寫入指定格式的JSON字符串:
[{ "id": 21, "name": "總經理", "pid": 0, "parent": true }, {"id": 26, "name": "技術部", "pid": 0, "parent": true }, { "id": 27, "name": "項目經理", "pid": 26, "parent": false }, {"id": 28, "name": "項目組組長", "pid": 26, "parent": false }, { "id": 29, "name": "安全部", "pid": 0, "parent": true }, {"id": 30, "name": "網絡安全部負責人", "pid": 29, "parent": false }, { "id": 31, "name": "項目安全測試員", "pid": 29, "parent": false }]
然后,寫JavaScript代碼:
var setting={ view: { selectedMulti: true }, check: { enable: true, }, data: { simpleData: { enable: true,//是否采用簡單數據模式 idKey: "id",//樹節點ID名稱 pIdKey: "pid",//父節點ID名稱 rootPId: -1,//根節點ID } } }; $(function () { //加載后端構建的ZTree樹(節點的數據格式已在后端格式化好了) $.ajax({ url: 'data.json', type: 'get', dataType: "json", success: (data)=> { console.log(data); $.fn.zTree.init($("#tree"), setting, data);//初始化樹節點時,添加同步獲取的數據 }, error: (data)=> { alert(data.message); } }); });
解釋
以上參數配置,大家最好去參看zTree.js官網API。
如果配置好了setting,那下面就要ajax請求數據并渲染出來。如上在ajax的success回調函數中使用$.fn.zTree.init($("#treeID"),setting,data)渲染樹節點,其中第一個參數:樹要渲染的位置、第二個參數:剛才寫的setting配置,第三個參數:要加載的數據。
如上,我們先看下效果:
其中我們最該關心的是如何實現節點的渲染,說白了就是要弄明白怎樣的數據結構zTree才能渲染出一棵樹。
Tree樹數據結構分析
首先,zTree渲染節點需要的數據一定是JSON格式的數據,且JSON數據的格式和simpleData配置參數有關;想要使用ajax這種方式渲染節點,你必須開啟enable: true,其次idKey是樹節點ID名稱,也就是說樹的每個節點都有一個id,我們在這里要指定被渲染的數據中展示id的名稱;其次要指定pIdKey,因為你的節點不會都是平級的沒有子節點,當需要子節點,就必須指定一個區分父子節點的ID名稱;最后就是rootPId表示根節點ID,即最上層的節點ID,一般寫為-1即可。
此時,你或許應該參考一下我這篇文章:Shiro實現權限管理之表結構設計 ,表結構的設計和tree樹的構建也算是有一部分的關系吧。
如果你的simpleData是這樣配置的:
simpleData: { enable: true,//是否采用簡單數據模式 idKey: "id",//樹節點ID名稱 pIdKey: "pid",//父節點ID名稱 rootPId: -1,//根節點ID }
那么你就應該提供這樣的JSON數據:
[{"id": "xx", "pid": "xx", "pid": "xx"},{"id": "xx",....},{....}]
只要名稱和JSON數據中對應就行,不然無法渲染出節點。
如何實現默認選中
實現默認選中,就是在初始化樹的時候,將(用戶)已擁有的節點選項選中。要知道所有的節點數據應該是從數據庫中讀取出出來的,例如這篇博文 權限管理系統數據庫表設計 中用戶都可能擁有一個角色,那么在遍歷角色樹的時候就應該默認選中一些節點表述用戶已經擁有了這個節點角色。
簡單一句話:遍歷需要默認選中的節點數據(ID..),調用zTree.js相關的方法根據(ID)實現默認選中。
首先我們需要了解:
| 函數 | 用處 | | -- | -- | | $.fn.zTree.getZTreeObj('') | 獲取zTree對象,根據div中指定的ID獲取此渲染的ZTree對象,下面的方法都用到此對象調用 | | zTree.selectNode(treeNode,addFlag,isSilent) | 根據上面獲取的zTree對象調用selectNode,參數一:要選中的節點數據;參數二:是否允許同時選中多個節點;參數三:為false選中節點自動滾動到可視區域,實現選中子節點的父節點默認展開 | | zTree.checkNode(treeNode,checked,checkTypeFlag,callbackFlag) | selectNode只實現選擇了節點,checkNode實現勾選節點,參數二:是否勾選節點;參數三:勾選父節點是否聯動勾選其下的子節點;參數四:是否自動觸發beforeCheck & onCkeck 回調函數 | | zTree.getNodeByParam(key,value,parentNode) | 獲取完全匹配節點數據的JSON對象,參數一:要精確匹配的屬性名稱;參數二:要精確匹配的屬性值;參數三:在某個父節點下查找 |
用法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="static/lib/bootstrap.min.css"> <link rel="stylesheet" href="static/lib/css/metroStyle/metroStyle.css"> <link rel="stylesheet" href="static/lib/css/demo.css"> </head> <body> <div class="zTreeDemoBackground"> <ul id="tree" class="ztree"></ul> </div> </body> <script type="text/javascript" src="static/lib/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="static/lib/jquery.ztree.core.min.js"></script> <script type="text/javascript" src="static/lib/jquery.ztree.excheck.min.js"></script> <script type="text/javascript"> var setting={ view: { selectedMulti: false }, check: { enable: true, }, data: { simpleData: { enable: true,//是否采用簡單數據模式 idKey: "id",//樹節點ID名稱 pIdKey: "pid",//父節點ID名稱 rootPId: -1,//根節點ID } } }; $(function () { //加載后端構建的ZTree樹(節點的數據格式已在后端格式化好了) $.ajax({ url: 'data.json', type: 'get', dataType: "json", success: (data)=> { console.log(data); $.fn.zTree.init($("#tree"), setting, data);//初始化樹節點時,添加同步獲取的數據 checkNodes(); }, error: (data)=> { alert(data.message); } }); }); //處理默認選中的方法 function checkNodes(){ //模擬數據庫中已存在的數據(要實現默認選中的數據) var data=[{"id": 21, "name": "總經理", "pid": 0},{"id":'27', "name": "項目經理", "pid": 26}]; var zTree=$.fn.zTree.getZTreeObj("tree"); //獲取zTree對象 data.forEach(row=> { zTree.selectNode(zTree.getNodeByParam("id", row.id), true, false); zTree.checkNode(zTree.getNodeByParam("id", row.id), true, false); }); } </script> </html>
如上,實現默認選中,在初始化樹后立即調用處理默認選中的方法即可。我們模擬默認選中的數據中包含了id和name以及pid,這些都是比較基礎的數據,ztree的selectNode和checkNode方法都是根據id實現選中的, 默認選中要提供的數據和渲染樹用的格式是相同的。其中:
如何獲取選中的節點
獲取選中的節點,只需要了解zTree.getCheckedNodes(),用來獲取選中節點數據的JSON對象。其中獲取到的選中節點數據包含一定順序:選中父節點永遠在選中子節點的最前面。
如果想要在提交表單的時候,將選中節點的值傳給后臺,就可以使用getCheckedNodes()方法獲取到選中節點數據,然后遍歷得到各個選中節點的數據。
如何實現單選
實現單選,只需要在setting的check中配置chkStyle: "radio"即可實現單選,但是,此時實現的單選只在同級節點上才能實現單選,也就是說你在同級節點上只能單選,但是在你可以同時選中子節點和父節點。
那么,在你調用getCheckedNodes()方法獲取選中節點數據時,其中也包含了選中的父節點,因為父節點可能只是個分組不一定要存入到數據庫中;那么此時你就要判斷下如果選中的節點的長度>0,那么就取索引位置的最后一個值;
<!--more-->
上面我們將的都是前端如何將JSON數據渲染成一棵Tree樹,但是渲染用的數據應該是沖數據庫中讀取的。下面我們應該學習一下后端如何實現封裝Tree樹用的JSON數據。
我們使用SpringMVC作為與后端交互的Web層框架,關于SpringMVC + Spring + Mybatis 框架的整合,大家可以參看我的這個項目 SSM框架整合
封裝實體類
想必大家一定知道@ResponseBody這個注解,如果方法或類上添加了這個注解,那么@RequestMapping()映射return的東西將不再是InternalResourcecViewResolver視圖解析器解析的視圖地址,而是JSON格式的數據。 那么想要讓SpringMVC相應一串[{"id": "xx", "name": "", "xx"},{"id": "xx", "name": "xx"}]這種格式的數據,我們就必須手動將數據封裝成這種格式,如此SpringMVC才能將對象轉換成JSON串。
我們會想到,我們可以將從數據庫中讀取的數據,依次存入到Map(或List)集合中,然后return map。當然,這是可行的,但是或許麻煩了些,因為整個項目中不止要構建一棵Tree樹,每次都要new Map重用率就太低了。所以,一個簡單的方式,就是手動創建一個實體類TreeEntity.java用以存放從數據庫中讀取到的數據,這樣每次構建Tree樹都能使用這個實體類對象。
TreeEntity.java屬性如下:
public class TreeEntity implements Serializable { private Long id; //節點的id值 private String name; //節點的名稱 private Boolean isParent; //是否是父節點 private Long pid; //當前節點對應父節點的id值 public TreeEntity(Long id, String name, Boolean isParent, Long pid){ this.id=id; this.name=name; this.isParent=isParent; this.pid=pid; } getter/setter .... }
如上,你會發現,這是不是和我們前面說的前端構建Tree樹的結構是一樣的呢。沒錯,我們前端既然定義了這種格式,后端就必須要給它一個這樣格式的數據。
Web層封裝Tree數據結構
這里不再講Dao層中如何查詢的數據,我們僅以一個最簡單的查詢(findAll查詢所有)來講述Tree的數據結構封裝。
先看代碼:
@ResponseBody @RequestMapping("/getZTreeForUserRoles") public List<TreeEntity> getTreeForUserRoles() { try { List<TreeEntity> treeList=new ArrayList<TreeEntity>(); List<Role> roleList=roleService.findAll(); for (Role role : roleList) { // 為tree樹節點添加數據,節點pid為0的都是父節點,其他為子節點 if(role.getPid() !=null){ if (role.getPid()==0) { treeList.add(new TreeEntity(role.getId(), role.getDescription(), true, (long) 0)); } else { treeList.add(new TreeEntity(role.getId(), role.getDescription(), false, role.getPid())); } } } return treeList; } catch (Exception e) { e.printStackTrace(); return null; } }
解釋
我們來看一下這個請求映射返回的數據格式是如何的:
如上,我們已經實現了目的。
拓展
上面的代碼中還要說明的就是調用TreeEntity的帶參構造函數傳入的參數值。我們定義的帶參構造函數如下:
public TreeEntity(Long id, String name, Boolean isParent, Long pid) { this.id=id; this.name=name; this.isParent=isParent; this.pid=pid; }
在為List<TreeEntity>集合循環添加值時,要弄清楚:
節點的id是每個節點的唯一標識,就像數據庫的主鍵值一樣,所以我們通常將其設置為數據庫中的主鍵值。并且以后也要獲取這個主鍵值。
節點的名稱name是前端展示的各個節點的名稱。而這些名稱應該和數據庫中的值是相同的,所以我們將其設置為數據庫的description的值。
父節點,我們在數據庫中已經定義了,即數據庫中存在一個字段pid,這個字段表示的是上級節點的id值,即如果存在上級節點(或叫上級分組),那么就給此row的pid字段設置為上級row的主鍵id值。
根據構造方法中的isParent字段,如果是父節點就直接手動設置為true,否則就設置為false。 如何判斷是父節點?根據數據庫(實體類)中已有的屬性值pid判斷,如果pid不為0就表示是子節點,如果pid是0就是父節點(因為主鍵值不可能為0)。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。