Intraweb一直是Delphi快速开发web应用的首选工具,但自带的控件较少,样式比较难看,TMS与IW倒是可用,可是要收费,对于我们这些习惯用免费的用户来说,想找个破解也比较费劲。EasyUI是基于JQuery开发的框架,内置的控件完全可以满足我们开发一般web程序的需求,而且是免费的,用起来也心安理得。下面我就IW如何结合EasyUI开发程序谈谈自己的一些心得,与大家交流一下。主要有以下几种方法:
  一、使用模板
  在IWForm内使用模板引入做好的html文件,结合IW自身的控件进行操控。这种方法虽说比较方便,但模板也有自身的缺点,内部不支持中文引用是一大Bug,目前IW都没有要解决的迹像。如果一定要用模板,也有方法规避,即汉字全部用网页转义“&#”加汉字的十进制编码。模板的使用有很多文章可供参考,也不是本章的重点,不做具体讲解。
  二、MVC设计模式
  IW使用MVC方式结合EasyUI设计程序,是本文的重点。我们知道IW与HTML静态页面的交互,可以通过javascript接口来实现,可以使用AddToInitProc('alert("欢迎")')这样的语句,也可以在控件的JavascriptEvent属性内添加js语句。本文介绍的方法完全将界面与数据处理分开,一律使用EasyUI来实现界面(完全不用IW的可视控件,数据库控件还是需要的),数据处理交给IW后台做。我们以开发一个简单的应用程序来一步步实现这些功能,同时会使用一定篇幅介绍EasyUI部分控件的使用(本文必须要有一定的javascript基础)。
  第一步:实现登陆界面。

  首先引入以下文件,后面其它页面也一样这样引用,直接贴代码:

 <span style="white-space:pre"> </span><link rel="stylesheet" type="text/css" href="easyui/themes/default/easyui.css"><link rel="stylesheet" type="text/css" href="easyui/themes/icon.css"><script type="text/javascript" src="easyui/jquery.min.js"></script><script type="text/javascript" src="easyui/jquery.easyui.min.js"></script><script type="text/javascript" src="easyui/locale/easyui-lang-zh_CN.js"></script>

   这些文件是必须引用的,easyui.css是自带的样式,icon.css是使用中的各种图标,easyui-lang-zh_CN.js是汉化文件(EasyUI对中文支持还是很不错的,如果觉得汉化得不够好,可以打开这个文件自行修改)。界面部分:

<form id="ff" class="easyui-form" method="post" data-options="novalidate:true">
<!--form提供了各种方法来操作执行表单字段,比如:ajax提交, load, clear等等。当提交表单的时候可以调用validate方法检查表单是否有效。
“data-options”控件的各种属性,form有以下属性:
属性名 类型  描述  默认值
novalidate  boolean     定义是否验证表单的字段,true:验证,false:不验证。   false
ajax    boolean     定义是否使用ajax提交表单,true:使用,false:不使用。    true
queryParams     object      当表单被提交到服务器的时候增加的额外参数列表。 {}
url string      提交表单动作的URL地址    null
--><table cellpadding="5"><tr><td>用户名:</td><td><input class="easyui-textbox" type="text" name="username" data-options="required:true" style="width:150px"/></td><!--
TextBox(文本框)是一个增强的输入字段组件, 它允许用户非常简单的创建一组表单。它是一个用于构建其他组合控件的基础组件,如:combo,databox、spinner等required:true表示文本框不能为空,下同。
--></tr><tr><td>密 码:</td><td><input class="easyui-textbox" type="password" name="passw" data-options="required:true" style="width:150px"/></td></tr></table></form><div style="width:216px;padding:5px 0px;height:30px"><a href="javascript:void(0)" class="easyui-linkbutton" οnclick="submitForm()" style="width:80px;float:left">登陆</a>
<!--easyui-linkbutton按钮组件,使用超链接按钮创建,提示:不要将它改为button类别,IE9以下浏览器会不正常,submitForm()提交数据,clearForm()清空数据--><a href="javascript:void(0)" class="easyui-linkbutton" οnclick="clearForm()" style="width:80px;float:right">取消</a></div></div></div>

  登陆界面基本完成,有些简陋,当然可以自行修改。下面实现提交数据和清空数据,用Javascript:

     function submitForm(){$('#ff').form('submit',{//这是EasyUI的Form自带功能,就是提交数据url:'Login.php', //需要把数据提交到的页面onSubmit:function(){//验证数据是否为空,如果为空就返回。return $(this).form('enableValidation').form('validate');},success: function(data){
//提交成功后的回调函数,data就是返回的数据if(parseInt(data)==1)
//我们在这里返回1和0,1表示成功登陆,在后台实现{window.location='main.html';
//登陆成功后,跳转到主程序}else{$.messager.alert('错误','用户名或密码错误!','error');
/*EasyUI消息提示框,就是alert的改进用法,显示警告窗口。
参数(依次调用):
title:在头部面板显示的标题文本。
msg:显示的消息文本。
icon:显示的图标图像。可用值有:error,question,info,warning。
fn: 在窗口关闭的时候触发该回调函数。 */$('#ff').form('clear');//清空数据,下同。}}    });}function clearForm(){$('#ff').form('clear');}

  文件另存为“index.html”,即首页,放在wwwroot下(注意easyui的相关文件也要放在这个目录下),启动程序后,就是直接访问这个页面了,没有“$”这个标志。
  登陆界面基本完成,数据需要提交到“Login.php”这个页面,按一般的做的法,新建一个IWForm,使用模板加载文件,本文用另一种思路,也是本文的关键:
用delphi新建一个Unit,命名Login单元,加入IW工程。

直接贴出代码(参考万一博客):

{新建Login 单元, 从 TContentBase 继承实现一个 TLogin 类}
unit Login;interface
uses Classes, IW.Content.Base, System.SysUtils,HTTPApp, IWApplication, IW.HTTP.Request, IW.HTTP.Reply, IWMimeTypes;typeTLogin = class(TContentBase)protectedfunction Execute(aRequest: THttpRequest; aReply: THttpReply; const aPathname: string; aSession: TIWApplication; aParams: TStrings): Boolean; override;publicconstructor Create; override;end;implementationuses ServerController,UserSessionUnit;
{ TLogin }constructor TLogin.Create;
begininherited;mFileMustExist := False;
end;function TLogin.Execute(aRequest: THttpRequest; aReply: THttpReply; const aPathname: string; aSession: TIWApplication; aParams: TStrings): Boolean;
beginaReply.ContentType := MIME_HTML;aReply.WriteString('这里就是返回到客户端的数据');Result := True;
end;end. {在 IWServerControllerBase.OnConfig  映射login.php}
usesIWInit, IWGlobal, IW.Content.Handlers, Login;procedure TIWServerController.IWServerControllerBaseConfig(Sender: TObject);
beginTHandlers.Add('', 'login.php', TLogin.Create);
//添加虚拟文件名,映射到服务器
end;

  直接列出代码大家可以不太清楚怎么回事,这里说明一下流程:
  客户端通过Form提交用户名和密码到“Login.php”,“Login.php”是通过服务器添加的一个虚拟文件,映射到从TContentBase继承实现的TLogin类,用THttpRequest接收提交的数据,并进行处理,用THttpReply.writestring写入返回客户端数据。这样登陆过程前台与后台代码均完成。

  第二步:实现主界面
  我们开发的是一个商品信息管理程序,主界面用EasyUI的Layout实现自适应浏览器(记得引入相关js和css):

<div data-options="region:'north',border:false" style="height:60px;background:#B3DFDA;padding:0px 10px;text-align:center">
<h3>商品信息管理系统</h3>
</div>
<div data-options="region:'west',split:true,title:'商品分类'" style="width:200px;padding:10px;"></div>
<!--<div data-options="region:'east',split:true,collapsed:true,title:'East'" style="width:100px;padding:10px;">east region</div>-->
<div data-options="region:'south',border:false" style="height:50px;background:#A9FACD;padding:10px;">
京ICP证000000号
</div>
<div data-options="region:'center',title:'商品简要信息'"></div>

  很好理解,即左西右东,上北下南加上中央的布局,右边不需要,我把它注释掉。

  页面设计思路是这样的,左边放一个Tree,用来显示商品分类,中央放GridData,用来显示商品信息列表,通过两个控件实现删除、添加、修改功能。
  west这个DIV内加入Tree:

<ul id="easyui_tt" class="easyui-tree"
data-options="
animate:true,//动画
lines:true,//显示树线
url:'Treedata.php',//上面有解释,需要提交的页面
method:'post',//提交方式Post,再强调一下必须用Post
onClick: function(node){//鼠标单击事件
QueryByID(node.id);//通过node.id来查询数据,讲DataGrid时再说
},
onContextMenu: function(e, node){//右键菜单
e.preventDefault();//必须用的
$(this).tree('select', node.target);//选择的Node
$('#mm').menu('show', {//EasyUI的菜单,非常简单
left: e.pageX,//弹出菜单的位置
top: e.pageY
});
}">
</ul>

  Tree的属性很多,其中一个比较重要的是node,即Tree的节点每个节点都具备以下属性:
  id:节点ID,对加载远程数据很重要。
  text:显示节点文本。
  state:节点状态,'open' 或 'closed',默认:'open'。
  如果为'closed'的时候,将不自动展开该节点。
  checked:表示该节点是否被选中。
  attributes: 被添加到节点的自定义属性。
  children: 一个节点数组声明了若干节点
  Tree的节点是通过url提交请求到服务器接收返回数据加载的,形成
  树的数据是JSon格式,我们可以分析一下:

[{    "id": 1,//对应node的ID,其他也是一一对应的    "text": "Node 1",    "state": "closed",    "children": [{ //子node   "id": 11,    "text": "Node 11"   },{    "id": 12,    "text": "Node 12"   }]
},{    "id": 2,    "text": "Node 2",    "state": "closed" //不展开节点
}]}

  同上面的“登陆”,我们从TContentBase继承实现一个 TTreeData 类直接复制模板,修改一个即可,注意加入IW工程,并在ServerController内映射“TreeData.php”。我们现在需要通过delphi来实现树,Tree的层越多就越复杂,我发现
不管通过什么语言动态实现Tree,都是非常麻烦的一件事,EasyUI的例子只能实现两层树。从数据库读取Tree数据,在数据库设计的时候有一个技巧,不知道大家是怎样处理的,我这里说一个我的方法:树的上下级之间用代码表示,2位数字代表根,4位数字代表下一级,依此类推,代码不能用纯数字,这样不好排序,我在数字前加个字母,这样通过“select*from Tree order by id”就可以把上下级排列在一起,而不是按代码大小排序。数据库就不多讲了,不在本文的范围,大家看一下我的源码里的数据库就知道了。建树代码如下(本想用JSon,无奈学不到家,只能用字符串拼接):

function BuildTree:string;
vari,j,old_ln,new_ln:Integer;id,s,title,ft:string;
begin
ft:='{"id":"%s","text":"%s"},';//Json格式
with UserSession.FDQuery1 do
beginOpen('select*from Tree order by id'); //按id排序可以将父子节点正好罗列在一起s:='[';old_ln:=0;//初始化开始节点ID的长度for i := 0 to RecordCount-1 dobeginid:=Fields.Fields[0].AsString;title:=Fields.Fields[1].AsString;new_ln:=id.Length-3;//新节点ID的长度,减去3除去了根节点的长度,方便计算//通过比较与上一节点ID的长度来判断节点的上下级关系if (new_ln=old_ln) then//与上一节点同等级s:=s+Format(ft,[id,title]);if new_ln>old_ln then //上一节点为父节点begins:=s.Substring(0,s.Length-2);s:=s+Format(',"state":"closed","children":['+ft,[id,title]);end;if (new_ln<old_ln) then //上一节点为子节点begins:=s.Substring(0,s.Length-1);for j :=1 to (old_ln-new_ln) div 2 dos:=s+']}';s:=s+Format(','+ft,[id,title]);end;Next;old_ln:=new_ln;//将当前节点ID长度赋予旧节点end;
end;s:=s.Substring(0,s.Length-1);for i := 1 to new_ln div 2 do //结束时需要判断是否为子节点,有几层s:=s+']}';result:=s+']';
end;

  以上代码已经注释,有什么不明白的地方我们再交流,可以实现N多级树,只要客户端支持,有的控件是不支持多级树的。Tree实现了,我们再实现右键菜单,onContextMenu:

onContextMenu: function(e, node){
e.preventDefault();
$(this).tree('select', node.target);
$('#mm').menu('show', {
left: e.pageX,
top: e.pageY
});

  注意$('#mm')这个就是右键菜单的JQuery标识,我们做一个删除、添加功能,代码如下:

<div id="mm" class="easyui-menu" style="width:120px;">
<div οnclick="addnode()" data-options="iconCls:'icon-add'">添加</div>
<div οnclick="removeit()" data-options="iconCls:'icon-remove'">删除</div>
</div>

  提示:EasyUI很多情况下只需要引用$('')类似的标识就可以将其他控件加进去。实现addnode()、removeit()以及其他功能:

<span style="white-space:pre">      </span>function appendn(r){//添加节点var t = $('#easyui_tt');var node =t.tree('getSelected');var pii=node.id;$.ajax({  type : "post",  url : "Treedata.php",  data : {Action:'Add',ID:pii,Title:r},  async : false,//这里必须用同步  success : function(data){  pii=data;}  });t.tree('append', {parent: (node?node.target:null),data: [{id:pii,text:r}]});}function removeit(){//删除节点var node = $('#easyui_tt').tree('getSelected');var pii=node.id;$.post('Treedata.php',{Action:'Del',ID:pii});$('#easyui_tt').tree('remove', node.target);}function collapse(){//树折叠var node = $('#easyui_tt').tree('getSelected');$('#easyui_tt').tree('collapse',node.target);}function expand(){//树展开var node = $('#easyui_tt').tree('getSelected');$('#easyui_tt').tree('expand',node.target);}function addnode(){//弹出添加节点对话框,用消息框$.messager.prompt('添加', '请输入需要添加的名称:', function(r){if (r){appendn(r);    }});}

  这段代码是用JQuery实现向IW提交数据,即把data以JSon格式提交到服务器$.post('Treedata.php',{Action:'Del',ID:pii});提交删除功能,是$.ajax的简单实现,顺便说一下,万一的博客提到

function TestPost(){var mydata="TestMYPost测试一下";executeAjaxEvent("&data="+mydata, null, "DoCallBack1", false, null, false);//中文在IE下乱码
}

  这样提交数据,用WebApplication.RegisterCallBack('IWCallBack1', DoCallBack1) 注册回调接收数据,我觉得用JQuery的post实现更简单,IWForm内用$.post需要这样:

$.post(GURLBase+"callback?",{callback:"DoCallBack1",data:"测试一下可以吗-----?"},function(data){processAjaxResponse(data);},"xml");//必须是xml格式
}//效果是一样的,也需要注册回调函数

  注:GURLBase等于'/$/'(看着非常不爽的美元符号),修改一下万一的代码:

function TestPost(){
var mydata=escape("TestMYPost测试一下");
executeAjaxEvent("&data="+mydata, null, "DoCallBack1", false, null, false);//中文在IE下乱码,需要escape
}

这样也支持中文了。
  服务器如何处理数据,登陆界面已经详解,基本类似,添加删除也不再列代码,大家可以直接看我的源码,用delphi实现真的很简易。
  Tree讲完,我们接着讲DataGrid:
  center这个DIV内加入:

<table class="easyui-datagrid" style="width:100%;height:400px"
data-options="singleSelect:true,collapsible:true,fitColumns:true,url:'GridData.php',
method:'post',pageSize:10,pagination:true,onDblClickRow:onDClickRow"
<!--
相同的属性不再说明,
singleSelect选择单行
collapsible定义是否显示可折叠按钮,EasyUI大部分控件继承自panel,一般可折叠
fitColumns列宽自适应
pageSize分页时每页显示的行数
pagination是否分布
-->
toolbar="#dg_tb"//工具栏,EasyUI可以这种方式嵌入其他控件
id="easyui_tb">
<thead><!--头部-->
<tr>
<th data-options="field:'codeID',width:80,halign:'center',editor:'text'">商品编号</th>
<!--field对应数据库字段halign标题居中
editor:'text'编辑样式为文本框
align:'center'整列居中
-->
<th data-options="field:'p_name',width:100,halign:'center',editor:'text'">名称</th>
<th data-options="field:'p_type',width:80,halign:'center',align:'center',editor:'text'">型号</th>
<th data-options="field:'p_tid',width:80,halign:'center',align:'center',editor:'text'">类别</th>
<th data-options="field:'p_pinpai',halign:'center',width:250,editor:'text'">品牌</th>
<th data-options="field:'p_price',halign:'center',width:60,align:'center',editor:'text'">价格</th>
<th data-options="field:'p_discount',halign:'center',width:60,align:'center',editor:'text'">折扣</th>
</tr>
</thead>
</table>
<div id="dg_tb" style="padding:3px"><!--工具栏-->
<span>商品编号</span>
<input id="codeID" class="easyui-numberbox" style="line-height:22px;border:1px solid #ccc">
<span>商品名称</span>
<input id="p_name" class="easyui-textbox" style="line-height:22px;border:1px solid #ccc">
<a href="#" class="easyui-linkbutton" plain="true" οnclick="doSearch()">查询</a>
<a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-add',plain:true" οnclick="appendr();">添加</a>
<a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-remove',plain:true" οnclick="remover()">删除</a>
<a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-save',plain:true" οnclick="acceptr()">修改</a>
<a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-undo',plain:true" οnclick="rejectr()">撤消</a>
</div>

DataGrid功能强大,也很复杂,本文只讲基本应用,大家可以看我上传的EasyUI帮助文件。从服务器端获取表格数据同上,数据也是JSon格式的,建一个MyGridData,上面讲Tree时留下一下函数未讲解QueryByID(node.id),JS如下:

function QueryByID(id){//以节点ID查询
var tb=$('#easyui_tb');
tb.datagrid({queryParams:{Action:'Q_ID',ID:id}});
/*queryParams是DataGrid提交数据时的参数,
也可以直接:tb.datagrid('load',:{Action:'Q_ID',ID:id}});
但是在测试中发现,这样提交后数据为空时,表仍然显示有数据,
也许是Bug,也许是我不会用。load即是post数据到服务器,同时
接收返回数据,GridData全部封闭好了。
*/
tb.datagrid('load');
}

  以ID查询数据在服务器端这样实现:

function QueryData(config:string):string;
vararrjson:JSONArray;ajson:JSONObject;i,j:integer;
beginarrjson:=JSONArray.Create;ajson:=JSONObject.Create;with UserSession.FDQuery1 dobeginOpen('select*from product where '+config);for I :=0 to RecordCount-1 dobeginfor j := 0 to Fields.Count-1 doajson.Put(Fields.Fields[j].DisplayName,Fields.Fields[j].AsString);
//形成'{aaa:"BBB",ccc:"DDDD"}'这样的字符串,不需要拼接字符串了。arrjson.AddJSON(ajson.ToString(4));
//字面上理解就是JSon数组,即[{},{}];ajson.Clear;
//清除ajson内的数据,不然ajson会不停put数据,类似js的push用法      Next;end;end;Result:='{"total":'+i.ToString+',"rows":'+arrjson.ToString(4)+'}';
//ToString(4)表示以4个空格缩进,不这样使用json数据会被转义
//datagrid数据多出的total是分页时用到的,表示总行数,rows表示当前显示页面
//如果不分页,可以直接: Result:=arrjson.ToString(4)'; arrjson.Free;ajson.Free;end;

  我是直接以查询条件为参数的,以便于扩展,这里用到了yxdJson,在我上传的控件中有,比较好用,其实就是形成'{aaa:"BBB",ccc:"DDDD"}'这样的语句,特别简洁,不用拼接字符串(拼接字符串是很痛苦的)。Tree的数据我也想用的,但死活不行,只好放弃。GridData是用服务器实现分页的,也特简单,即提交page和rows这个两个参数到服务器,代码大家自已下载,delphi实现也非常简单,sql查询时加入limit (page-1)*rows,rows条件即可。注意字符串与整数的变换。实现查询、删除、添加、修改功能,客户端js:

function doSearch(){//查询功能
$('#easyui_tb').datagrid('load',{
Action:'Q_DN',
id: $('#codeID').val(),
p_name: $('#p_name').val()
});}//load参数即可,上面有讲解
var editIndex = undefined;
var ExecType='';
function endEditing(){//结束编辑
if (editIndex == undefined){return true}
if ($('#easyui_tb').datagrid('validateRow', editIndex)){
var ed = $('#easyui_tb').datagrid('getEditor', {index:editIndex,field:'codeID'});
$('#easyui_tb').datagrid('endEdit', editIndex);
editIndex = undefined;
return true;
} else {
return false;
}
}
function onDClickRow(index){//双击编辑整行数据
if (editIndex != index){
if (endEditing()){
var  tt=$('#easyui_tb').datagrid('selectRow', index);
var EditID=tt.datagrid('getSelected')['codeID'];//选择行的codeID值
tt.datagrid('beginEdit', index);
editIndex = index;
ExecType='update,'+EditID;//提交到服务器update
} else {
$('#easyui_tb').datagrid('selectRow', editIndex);
//数据库必须依靠主键为标志来更新。
}
}
}
function appendr(){//添加
if (endEditing()){
$('#easyui_tb').datagrid('appendRow',{p_discount:'1.0'});
editIndex = $('#easyui_tb').datagrid('getRows').length-1;
$('#easyui_tb').datagrid('selectRow', editIndex)
.datagrid('beginEdit', editIndex);
//添加一行空行
ExecType='insert into,';//提交到服务器insert
}
}
function remover(){//删除
var  tt=$('#easyui_tb').datagrid('getSelected');//找到选择行
if (tt==undefined) return;
//没有选择就退出
var Delindex=$('#easyui_tb').datagrid('getRowIndex',tt);
//选择行的行号
var DelID=tt['codeID'];//主键,用于删除
$.messager.confirm('删除','您确认想要删除记录吗?',
function(r){ if (r){
$('#easyui_tb').datagrid('deleteRow', Delindex);
$.post('GridData.php',{Action:'delete',id:DelID});
//提交delete
}});
editIndex = undefined;//这个本程序没用上,是单击时用的
}
function acceptr(){//修改编辑的数据,添加或编辑后,需要修改数据,提交到服务器
//不修改只是客户端更新,服务器端数据库没变
if (endEditing()){
$('#easyui_tb').datagrid('acceptChanges');
if (ExecType=='') return;
var selrow=$('#easyui_tb').datagrid('getSelected');
var row=new Array();
if(selrow!=undefined)
row.push(selrow['codeID'],selrow['p_name'],selrow['p_type'],selrow['p_tid'],selrow['p_pinpai'],selrow['p_price'],selrow['p_discount']);
//push就是将数据压入数组
var param=ExecType.split(',');//分割字符串为数组,delphi的用法类似
if(param[0]=='update')
{
$.post('GridData.php',{Action:param[0],id:param[1],Rowdata:row.toString()},function(data){alert(data)});
//update时要提交动作、codeID和更新后的数据,
//post的参数function(data){alert(data)就是服务器返回数据。
}
if(param[0]=='insert into')
{
$.post('GridData.php',{Action:param[0],Rowdata:row.toString()},function(data){alert(data)});
//insert时要提交动作和插入后的数据
}
ExecType='';
}
}
function rejectr(){//取消
$('#easyui_tb').datagrid('rejectChanges');
ExecType='';
editIndex = undefined;
}
function getChanges(){
var rows = $('#easyui_tb').datagrid('getChanges');
return rows;
}

  服务器实现这些功能用下面这个函数:
function Exec_SQL(act,id,row:string):string;
  源码自己去看,很简单,就是操作数据库。本文基本完成,最后讲一下这种方式未完成的功能:直接使用http://xxx.xxx.xxx/main.html可以不用登陆就能进入主界面,显然不是我们所期望的,可以在主界面加入验证登陆的功能,也很简单,可以在页面加载之前$.post提交验证信息到login.php,里面代码已经写了,只是客户端没有添加。还有第三大点。
  三、动态加载
  动态加载简单说就是,客户端还是单独做出来,不用放在wwwroot下面,引用js和css时需要在路径前面多加一个“/”即可。仍然从TContentBase 继承实现一个类,在函数中这样实现 :

function TMyIndex.Execute(aRequest: THttpRequest; aReply: THttpReply; const aPathname: string; aSession: TIWApplication; aParams: TStrings): Boolean;
varss:Tstrings;
beginaReply.ContentType := MIME_HTML;ss:=TstringList.create;ss.loadformfile('做好静态页面');aReply.WriteString(ss.text);ss.free;Result := True;
end;

  这样显而易见是比较安全的,可以在加载主界面前先验证有无登陆,还可以在加载页面中加一些类似模板替换标识,动态加载时,将这些标识替换成本页面需要展示的内容,实现header、body、footer共用。

  本文所需要工具:delphiXE7+Intraweb 14.0.38

  源码

Intraweb之EasyUI篇相关推荐

  1. 【EasyUI篇】Combo自定义下拉框组件

    微信公众号:程序yuan 关注可了解更多的教程.问题或建议,请公众号留言; 查看--> 全套EasyUI示例目录 20.Combo自定义下拉框组件 这组件不可以通过class方式进行定义 JSP ...

  2. 【EasyUI篇】TreeGrid树表格组件

    微信公众号:程序yuan 关注可获得更多干货哦!.问题或建议,请公众号留言; ------------------------------------------------ 关注小编微信公众号获取更 ...

  3. 【EasyUI篇】Accordion分类组件

    微信公众号:程序yuan 关注可了解更多的教程.问题或建议,请公众号留言; 查看--> 全套EasyUI示例目录 9.Accordion分类组件 JSP文件 <%--Created by ...

  4. 【EasyUI篇】PropertyGrid属性表格组件

    微信公众号:程序yuan 关注可获得更多资源.问题或建议,请公众号留言; 查看--> 全套EasyUI示例目录 28.PropertyGrid属性表格组件 JSP文件 <%--Create ...

  5. 【EasyUI篇】Resizable (调整大小组件)

    微信公众号:程序yuan 关注可了解更多的教程.问题或建议,请公众号留言; 查看--> 全套EasyUI示例目录 Resizable (调整大小组件) JSP文件 <%--Created ...

  6. 【EasyUI篇】LinkButton按钮组件

    微信公众号:程序yuan 关注可了解更多的教程.问题或建议,请公众号留言; 查看--> 全套EasyUI示例目录 5.LinkButton按钮组件 JSP文件 <%--Created by ...

  7. 【EasyUI篇】一整套EasyUI示例集锦

    目录: 1.可拖动组件Draggable 2.可放置组件Droppable 3.调整大小组件Resizable 4.Tooltip提示框组件 5.LinkButton按钮组件 6.ProgressBa ...

  8. EasyUI学习笔记8:MIS开发利器_ datagrid插件(下)(终结篇)

    为什么80%的码农都做不了架构师?>>>    一.引言 最后一篇是easyui与struts传递数据.拖了好多天,因为一直没想好怎么写.这部分代码参考了一个开源项目,很早之前写的, ...

  9. Spring+SpringMVC+MyBatis+easyUI整合基础篇(一)项目简述及技术选型介绍

    作者:13 GitHub:https://github.com/ZHENFENG13 版权声明:本文为原创文章,未经允许不得转载. 萌芽阶段 很久之前就开始打算整理一下自己的技术博客了,由于各种原因( ...

最新文章

  1. eclipse 启动tomcat, java.lang.ClassNotFoundExcepti
  2. DevOps滚动部署
  3. CSS Hack 和向后兼容
  4. SCons命令 之 从入门到精通
  5. 【CodeForces - 761D 】Dasha and Very Difficult Problem (构造,思维)
  6. iBatis的基本配置+CRUD操作
  7. 关闭窗口(window.close)
  8. 别整那些花里胡哨的,女孩子喜欢简单直接的男生
  9. SHELL下把一个文件附加到另外一个文件,注意编码问题
  10. 后台管理系统--毕业设计02
  11. 简单的权限管理系统——数据库设计和实现
  12. ps 22.4.3版你值得拥有!支持m1转译运行 https://mac.orsoon.com/Mac/180336.html
  13. delphi 各新版本特性收集
  14. Unity 一起看+弹幕 Socket通信
  15. 关于InnoDB存储引擎 text blob 大字段的存储和优化--转载
  16. 对ResNet的理解
  17. 硬核干货合集!500+篇Java干货技术文章整理|资源|书单|工具|面试指南|强烈建议打开!
  18. 阿里最新春招面经,腾讯 / 美团 / 字节 1 万道 Java 中高级面试题
  19. java 搭建http服务器_搭建简单的HTTP服务器
  20. MT4如何设置手机app通知

热门文章

  1. 非常详细的FastDFS整合springBoot教程-带文件下载地址
  2. 如何用PhotoShop去掉图片上的某些文字
  3. 登录令牌 Token 介绍
  4. vue实现 文件重命名
  5. 苹果手机充电口接触不良怎么办_手机充电插口松动!声音变小!手机死机!怎么办?...
  6. 蚁群算法(ant system,AS)
  7. 啤酒和饮料,切面条(python)
  8. 信息安全等级测评师考试重点梳理
  9. 零基础编程教学实录-000 思考要与不要
  10. 建立大学生职业成长规划4个步骤