设计有复杂客户端Script的服务器控件

    使用ASP.NET的服务器控件,可以极大的提高我们Web开发中组件的复用性。不过由于ASP.NET默认的__doPostBack传输机制,对于我们在Web页上开发DHMTL特性的功能没有什么实质的帮助,因为我们不可能每次HTML属性修改都doPostBack,这样的效率和用户体验会死人的哦~~

    所以这时候使用客户端Script是一个很好的办法。那我们就用呗,可是问题就谁之而来了。使用Script来操作DHTML,需要获得被操作HTML元素对象的引用(废话,不然怎么操作?!)。我们最常用的方法是:使用HTML元素的ID来引用或者使用document对象的方法:getElementById、getElementsByName 和 getElementsByTagName。由于getElementsByName 和 getElementsByTagName获得的都是一个HTML元素对象集合,所以最常用的就是getElementById了。可是对于ASP.NET的服务器端控件,要在该控件PreRender的时候才能准确的获得其ClientID属性。而且就算我们取到了HTML元素的ID,我们还需要把这个ID hard-coding到被Register到页面的Script里去。这里的复杂程度就可大可小很难说了 what_smile.gif

    这样一来每次修改Script都要很麻烦的到控件的RegisterClientScript方法里去修改Script,并处理好需要动态写入Script的参数。更麻烦的是如果页面允许多个这样的控件Render,还需要考虑会不会ID冲突等问题,虽然ASP.NET控件Render时候会自动保证控件和其子控件的ID是unique的,可是其它的HTML元素就比较的麻烦了。而且大量的ID使用,也会给Web的设计带来一些小麻烦,因为也存在需要避免ID重复的问题。

    所以在我管理有复杂客户端Script的服务器控件时,我都不给其中的HTML元素设置ID,并且也不在客户端脚本中使用任何和HTML元素ID有关的方法去引用它们。那么怎么引用呢?使用HTML元素在DHTML对象树中的Hierarchy来查找它们就行了。当我们在IE中操作这个"控件"(已经就是HTML元素了)时,在该控件最外层作为container的HTML元素里俘获event,然后使用其event.srcElement,就可以以它为起点来查找需要的HTML元素了。比如:
None.gif < table  border ="1"  ondblclick ="ShowOrHideSpan(this)"  style ="border-collapse: collapse;" >
None.gif    
< tr >
None.gif         
< td  name ="title" >
None.gif             Tilte
</ td >
None.gif    
</ tr >
None.gif    
< tr >
None.gif         
< td >
None.gif             
< span > Content: asdf asdf asdf </ span ></ td >
None.gif    
</ tr >
None.gif
</ table >
我们想实现double click表格中的Title来隐藏或显示Content,怎么弄呢?

    使用如下JScript代码:
ExpandedBlockStart.gif ContractedBlock.gif < script  language ="javascript" > dot.gif
InBlock.gif
function ShowOrHideSpan(elmt)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    
var srcElmt = event.srcElement;
InBlock.gif    
if ( srcElmt && srcElmt.tagName == 'TD' && srcElmt.name == 'title' )
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif         
var span = FindChildElement(elmt, 'SPAN');
InBlock.gif         
if ( span.style.display == 'none' )
ExpandedSubBlockStart.gifContractedSubBlock.gif         
dot.gif{
InBlock.gif              span.style.display 
= 'inline';
ExpandedSubBlockEnd.gif         }

InBlock.gif         
else
ExpandedSubBlockStart.gifContractedSubBlock.gif         
dot.gif{
InBlock.gif              span.style.display 
= 'none';
ExpandedSubBlockEnd.gif         }
       
ExpandedSubBlockEnd.gif    }
   
ExpandedBlockEnd.gif}

None.gif
</ script >
    这段Script中的FindChildElement(elmt, 'SPAN')就是在以elmt为起点遍历DHMTL对象树,一找出SPAN元素。当然这个示例只是一个demo,或许你会说,把事件监听放到第一个tr上多好,可那不是我们在这个demo中关心的东西。在实际的控件开发中可能会比这复杂的多,不过原理就是这样弄了,完全不依赖任何的ID。

    不过这种方式也还是有些不足,因为有时我们会发现FindChildElement相对于FindParentElement不是那么容易确定,一个起点元素的parent肯定是唯一的,而它的child显然可能是很多个。不过在我觉得在控件开发中注意一下HTML元素的Hierarchy比管理它们ID要容易得多,而且也不会对Script产生太大的影响。

    欢迎您的讨论和建议~~

    附一、FindChildElement(element, tagName)源代码(先深遍历):
ExpandedBlockStart.gif ContractedBlock.gif < script  lanuage ="JavaScript" > dot.gif
InBlock.gif
function FindChildElement(element, tagName)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    
var isFounded = false;
InBlock.gif    
var elements = element;
InBlock.gif    
var result = element;
InBlock.gif    
if ( element.tagName == tagName )
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return element;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
while(!isFounded && elements != null && result != null && result.tagName != tagName)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        elements 
= elements.childNodes;
InBlock.gif        
forvar i=0 ; elements != null && i < elements.length ; i++ )
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            result 
= elements.item(i);
InBlock.gif            
var result2 = FindChildElement(result, tagName);
InBlock.gif            
if ( result == null || result2 == null )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
continue;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if ( result.tagName == tagName || result2.tagName == tagName )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if ( result2.tagName == tagName )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    result 
= result2;
ExpandedSubBlockEnd.gif                }

InBlock.gif                isFounded 
= true;
InBlock.gif                
break;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
if ( isFounded )
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return result;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return null;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
</ script >
    在某些时候我们可以不用这个遍历算法,而使用element.all.tags(tagName)来获取Child Element,这个依赖于该页面的HTML元素之间的Hierarchy。

    附二、FindParentElement(element, tagName)源代码:
ExpandedBlockStart.gif ContractedBlock.gif < script  lanuage ="JavaScript" > dot.gif
InBlock.gif
function FindParentElement(element, tagName)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    
while(element != null && element.tagName != tagName )
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        element 
= element.parentElement;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
if ( element != null && element.tagName == tagName )
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return element;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
return null;
ExpandedBlockEnd.gif}

None.gif
</ script > None.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JosunScript 脚本组件是一个采用ATL技术编写的高效稳定的脚本解析器。 能让你的CS模式程序(Vc、VB、Delphi、BC等)轻松解析VbScriptJavaScript脚本语言。 大大增强你的程序逻辑处理的灵活性和程序的交互能力,轻松实现从BS系统提供的页面接口获取数据信息。 最大程度实现程序功能的免编译(只要修改脚本文件即可),为你的用户提供“热插拔”式的升级。 尤其适合于各种流程化的程序设计(工作流函数的操作、呼叫中心系统IVR流程化的设计等等)。 本控件使用简便,开发者可根据本文档提供的例子根据自己的实际需求在例子上稍作修改即可。 主要的功能有: 1.加载脚本文件 2.获取脚本中的函数列表 3.获取脚本中的全局变量列表 4.按变量名称 设置、获取 脚本文件里的全局变量值 5.直接执行 文本、变量 中设置的脚本代码 6.能获取文本脚本执行结束后脚本里面的变量返回值,返回给调用者,实现脚本技术与其他语言技术的交互. 7.按列表返回的函数、过程名称执行相应的函数、过程。自定义入口参数,并返回执行结果给调用者,实现脚本技术与其他语言技术的交互. 8.实现远程、本地 xml文件的解析,免去在程序内部编写复杂的xml操作类,尤其是像VB这样的程序, 可以大大节约开发时间(本压缩包内的VB的例子就是最典型最简单的解析xml的例子)。 9.可以利用xmlhttp实现asp、jsp等页面的数据的存取解析,轻松访问第三方的数据 10.利用强大的VBScript脚本技术可以实现数据库接口,轻松将程序中的变量写入第三方的数据库中 如果您正在被流程设计中繁杂的逻辑判断、为第三方提供数据接口而烦恼,如果你想在您的产品中嵌入 功能强大、高度灵活的脚本功能增强您的产品的竞争力,JosunScript控件可以助您一臂之力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值