树结构菜单
需求1
在页面的左侧建立一个树形的菜单, 这个菜单要求含有点击即展开下级功能. 菜单的结构是动态变化的, 每次获取需要调用后台接口, 通过WebSocket获取
分解需求即可认为是以下两点
1. 前端如何建立WebSocket通信
2. 如何生成树形菜单在这里插入代码片
1. 建立WebSocket通信
- 为什么不采用Http来获取?
因为项目需要用到长连接来获取例如文件, 点击菜单的目录结构, 上传文件等, 综合考虑采用WebSocket是最好的方法
2.抒写简单的WebSocket的Demo
/*
*略去部分解析代码, 根据项目不同可有所改变
*1. 为什么要将Json转成string: 与后台的解析统一, 传输和接受我们都是采用string的格式
*2. command[]数组的作用: 存储每次发送的命令,命令的格式根据不同的项目来改变, 不同的项目前后端约定的格式不一致
*3. 难点问题:
1. 如果多台电脑同时连接后台后台
2. 如果同一台电脑打开多个网页连接后台
这两种情况后台怎么知道把消息推送给谁?
最开始的时候我们想采用时间, 然后就满足不了第一种条件
查询可知生成唯一ID UUID就可以解决这个问题, 有需要了解更详细的可以百度
*/
function WebSocketTest(url) {
if ("WebSocket" in window) {
// 打开一个 web socket
ncListWs= new WebSocket(url);
ncListWs.onopen = function () {
// Web Socket 已连接上,使用 send() 方法发送数据
console.log("客户端发送数据:");
ncListWs.send(JSON.stringify(command[0])); //将Json转成strin的形式,若在外面直接调用send方法即可完成发送
};
ncListWs.onmessage = function (evt) //服务器返回消息的处理地方
{
// tempMsg: 此处省略了处理的过程, tempmsg为evt.data, 由于每个项目不同此处略去,以免造成干扰
if(tempMsg[1] == "menuList")
{
}
//获取文件列表信息
if(tempMsg[1] == "dir")
{
}
//下载文件
if(tempMsg[1] == "downloadfile")
{
}
};
ncListWs.onclose = function () {
// 关闭 websocket
console.log("连接已关闭...");
};
}
else {
// 浏览器不支持 WebSocket
console.log("您的浏览器不支持 WebSocket!");
}
}
/*
* 获取UUID作为WEBsocket的唯一标识, 解决上述代码问题3,每次发送的时候把这个作为ID标识发送
* */
function GetUUid() {
var d = new Date().getTime();
if (window.performance && typeof window.performance.now === "function") {
d += performance.now(); //use high-precision timer if available
}
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
};
2. 构建树菜单结构
树菜单的构建可以分为两种方法, 在此只讲一种利用插件完成的树菜单
//需要用到的css js引入
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link href="https://cdn.bootcss.com/bootstrap-table/1.11.1/bootstrap-table.min.css" rel="stylesheet">
<link href='{{ static_url("css/bootstrap-treeview.css") }}' rel="stylesheet">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap-table/1.12.1/bootstrap-table.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap-table/1.11.1/locale/bootstrap-table-zh-CN.min.js"></script>
<script src="https://cdn.bootcss.com/jquery.form/4.2.2/jquery.form.min.js"></script>
需要了解更多树形可以百度插件的其余内容
// html
<div id = "tree">{#树结构#}
</div>
// js
//增加树结构菜单节点
menuTreeData.push( {
text: tempMsg[index],// tempMsg为服务端返回的数据
href: '#'+ index,
tags: ['0'] //可以不加tage[0], 方便后续判断
});
// 树结构菜单
function TreeData() {
$('#tree').treeview({
color: "white",
levels:1,
expandIcon: 'glyphicon glyphicon-chevron-right',
collapseIcon: 'glyphicon glyphicon-chevron-down',
nodeIcon: 'glyphicon glyphicon-bookmark',
data: menuTreeData,
backColor: "rgba(255,255,255,0)",
onhoverColor: "rgba(255,255,255,.15)",
selectedBackColor: "", //当节点被选中时的背景色
selectedColor: "#FFFFFF", //当节点被选中时的前景色
showBorder: false,
onNodeSelected: function (event, data) {
//此处为点击事件
},
});
}
需求2
点击boostreap table 里面的文件夹可以跳转到下一级
// 类似百度云的点击跳转层次,此代码是boostreap table columns内的一个对象
//实现的内容是如果点击的是文件夹则调用clickFolderName()函数刷新表格的数据
{
field: 'FileName',
title: '文件名',
align: 'left',
valign: 'left',
formatter: function(value,row,index){
var htmlApd = '';
var fileType = row.FileType;
if(fileType == "folder")
{
htmlApd = '<img style="float: left;display: block" src="/static/img/file_capture/Folder.png"><span style="margin-left: 10px;cursor: pointer;" onclick="clickFolderName(\'' + index + '\') "> ' +value+'</span>';
}else {
htmlApd = '<img style="float: left;display: block" src="/static/img/file_capture/File.png"><span style="margin-left: 10px;cursor: pointer;"> ' +value+'</span>';
}
return htmlApd;
}
}
需求3
在表格某一个单元格内增加下载的按钮点击即可完成下载, 若下载的文件名字与点击的不同则需要把文件名改为一致
分解为:
步骤1. boostreap table内增加一个点击的按钮
步骤2. 点击点击按钮触发时间ws.send发送给服务器, 服务器返回一个下载的url
步骤3. 等待服务器上传需要下载的文件到文件服务器上, 通过http拉取文件服务器的文件
步骤4. 拉去的时候判断名字是否一致, 若不一致则改名, 一致直接下载
//******步骤一
//1. boostreap table内增加一个点击的按钮 此代码是boostreap table columns内的一个对象
{
field: 'operate',
title: '操作',
align: 'left',
valign: 'left',
events: operateEvents,
formatter: operateFormatter //自定义方法,添加操作按钮
}
// 2.此代码位于boostreap之外
function operateFormatter(value, row, index) {
if(row.FileType == "folder")
{
return "";
}
return [
'<button id="btnUpDown" type="button" class="btn btn-default" >下载</button>',
].join('');
}
//3. 此代码置于boostreap之前, 三个代码从上到下的顺序是 3 1 2
window.operateEvents={
"click #btnUpDown":function (e, value, row, index) {
//******步骤2
ncListWs.send(JSON.stringify(command[2]));//向服务器推送下载文件的信息,在ommessage处处理响应
},
}
//******步骤3 步骤四
/*
* 上方WebSocketTest里面添加
*/
步骤3的难点在于以下几个问题:
文件的下载我试过几种方法,
第一种例如<a标签的下载, 这种下载的方式可以直接改名, 但是缺点是如果下载的源和自己网站不是
同源那么会导致重命名失效
第二种就是上面采用的方式, 此代码位于WebSocketTest->onmessage内
$.ajax({
type:"get",
url:httpUrl,
async:false,
success:function(data){
downLoad(dwFileData,dwFileName);
}
});
//downLoad函数定义
function downLoad(content, filename) {
// 创建a标签
var eleLink = document.createElement('a');
// 设置a标签 download 属性,以及文件名
eleLink.download = filename;
// a标签不显示
eleLink.style.display = 'none';
// 获取字符内容,转为blob地址
var blob = new Blob([content]);
// blob地址转为URL
eleLink.href = URL.createObjectURL(blob);
// a标签添加到body
document.body.appendChild(eleLink);
// 触发a标签点击事件,触发下载
eleLink.click();
// a标签从body移除
document.body.removeChild(eleLink);
}
为什么要采用这种方法下载文件, 因为如果文件为XML的时候要下载采用from等window.opend等方式有时候并不是下载文件
而是打开文件, 所以我们通过Ajax把文件读取成自己网页的string流文件通过<a标签下载, 这样不会产生不同源而不能改文件名
遗留问题
当下载文件为XML, 若XML文件抒写不规范. 会导致下载的时候缺失(强烈提醒各位猿门抒写的时候一定要规范啊,不然前端两行泪)
具体的表现如下
目前还没有好的解决方法, 希望有大神看到此篇文章能够提一些解决方案, 本人前端被迫学习. 刚刚入门几个月,很多东西不熟悉, 如有理解偏差请勿见怪
2019/7/17解决遗留问题
两种XML的抒写方式均为正确格式只是第二种是浏览器对没有值做的优化处理 两种的结果调用都是一致