asp.net 无法确保在注册的 javascript 内不存在重复定义_asp.net技巧
2009-07-29 01:01
351 查看
asp.net 无法确保在注册的 javascript 内不存在重复定义_asp.net技巧
在ASP.NET 2.0中,我们使用Page.ClientScript属性(也就是个ClientScriptManager对象)的一些名字以Register开头的方法注册客户端脚本,这是大家都知道的。
理论上应该怎么避免冲突
先说说为什么要这样注册脚本,而不用Response.Write直接输出。举个例子,你用3个DropDownList做了一个输入日期的区域,分别代表年/月/日,然后你为了防止用户输入2007/02/31,所以你决定把这3个DropDownList做成级联的,也就是随着年和月的输入改动,日的可选项跟着改动。这时候你能通过写一些JavaScript来实现级联,例如定义一个名为updateDateRange()的JavaScript函数负责更新DropDownList,然后直接把这些JavaScript放到C#的字符串里,并且使用Response.Write输出。这些代码用起来会非常正常,直到有一次你的页面需要输入两个日期。
在需要输入两个日期的那个页面上,你把3个DropDownList复制粘贴了一遍,也把输出的JavaScript的那段代码复制粘贴了一遍,接着根据两处ID的不同做了相应的修改,结果有一组级联无法正常运行起来。你查看服务器端输出的HTML,接着恍然大悟??原来有两个updateDateRange()函数。于是你把updateDateRange()改为updateDateRange(yearControlClientId, monthControlClientId, dateControlClientId),同时把JavaScript删减为仅输出一遍,这时候无论哪组级联都使用同一个函数,他们根据调用时输入的DropDownList.ClientID来区分。
又有一天,你决定把这组级联封装为一个UserControl,做起来当然还是复制粘贴大法,也就是把3个DropDownList和JavaScript复制进UserControl,然后把UserControl的引用复制回原本的调用处。忙完之后,发现那个有两个日期输入的页面又出错了,原来updateDateRange(yearControlClientId, monthControlClientId, dateControlClientId)又被重复输出了,因为页面上放入了两个UserControl所以JavaScript被输出了两遍,并且没办法减少输出次数。 http://www.knowsky.com 这时候你能使用Page.ClientScript.RegisterClientScriptBlock解决问题,他通过type和key这两个参数确定脚本是否被重复注册,而被重复注册的脚本仅会输出一次。为什么要type和key两个参数呢?以前ASP.NET 1.x的同类函数只有key一个参数,这带来的问题是可能两个不同的控件设计时都使用了同一个key来注册自己的脚本,结果其中一个控件脚本的成功输出必然会抑制另一个控件脚本的输出。加上了type参数,各控件都用自己的类型作为标识,这样就能有效避免注册时冲突。
为何无法真正避免冲突
关于这个问题,我们先看看ASP.NET内部定义的JavaScript是以什么方式命名的。通常,private的全局函数或变量,命名都以双下划线开头,例如大家熟悉的__doPostBack,或是WebPartManager在客户端使用的__wpm。而public或protected的全局函数或变量,一般就似乎C#那样使用Pascal命名法。具体的例子,大家能用Reflector看看System.Web.UI的资源中的那些js文件。
我们暂时就假设这种命名法是正确的,然后模仿着去在自己研发的控件中实践。事实上非常多控件研发者也确实这样做了,比较多的专业控件中你都能看到双下划线开头命名的函数或变量,这至少能避免和控件使用者在页面上注册的函数或变量冲突,因为在页面上注册的函数或变量通常都采用比较简单的命名法。
如果目前我们要做一个浮动上下文菜单,也就是当你的鼠标移动到某个HTML元素上时该浮动菜单自动出现,当鼠标离开元素并且也不在菜单上时,菜单自动消失。为了方便用户操作,我们允许用户鼠标移动过程中稍微离开菜单区域,所以定义当鼠标离开菜单区域若干时间后才让菜单消失,而这个时间在客户端保存在__disappearAfter变量中。这个控件看起来什么问题都没有,直到你把他和ASP.NET 2.0自带的Menu控件放在同一个页面上,因为Menu控件也有类似的功能,而且和我们的控件相同Menu控件选择了将时间变量保存在一个名为__disappearAfter的变量中。
现然,作为ASP.NET框架的使用者,框架没有声明这个变量的名字不允许使用,我用了有问题当然就能认为是框架的错。Brad Abrams写了一本《.NET设计规范/Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries》,里面却完全没有提及JavaScript和CSS的规范,似乎在ASP.NET中使用到的JavaScript和CSS都是琐碎的不能在琐碎的事情,所以完全不值得一提。
事实上,既然ASP.NET允许一个页面上不同的控件设计者引入不同的JavaScript和CSS,就必须提供一种方法去管理潜在的命名冲突。如果是JavaScript,我们能考虑使用ASP.NET AJAX的namespace来避免冲突,下一代代号为Orcas的Visual Studio和ASP.NET将内置ASP.NET AJAX支持,所以其内置控件所使用的JavaScript应该也会有namespace,这样就有有效降低冲突概率。至于CSS命名冲突,暂时没有好的解决放案,只能依赖控件设计者的习惯了,你能考虑为你的控件根元素附上一个namespace以示区分,这样也算是降低冲突概率的一个办法。
在ASP.NET 2.0中,我们使用Page.ClientScript属性(也就是个ClientScriptManager对象)的一些名字以Register开头的方法注册客户端脚本,这是大家都知道的。
理论上应该怎么避免冲突
先说说为什么要这样注册脚本,而不用Response.Write直接输出。举个例子,你用3个DropDownList做了一个输入日期的区域,分别代表年/月/日,然后你为了防止用户输入2007/02/31,所以你决定把这3个DropDownList做成级联的,也就是随着年和月的输入改动,日的可选项跟着改动。这时候你能通过写一些JavaScript来实现级联,例如定义一个名为updateDateRange()的JavaScript函数负责更新DropDownList,然后直接把这些JavaScript放到C#的字符串里,并且使用Response.Write输出。这些代码用起来会非常正常,直到有一次你的页面需要输入两个日期。
在需要输入两个日期的那个页面上,你把3个DropDownList复制粘贴了一遍,也把输出的JavaScript的那段代码复制粘贴了一遍,接着根据两处ID的不同做了相应的修改,结果有一组级联无法正常运行起来。你查看服务器端输出的HTML,接着恍然大悟??原来有两个updateDateRange()函数。于是你把updateDateRange()改为updateDateRange(yearControlClientId, monthControlClientId, dateControlClientId),同时把JavaScript删减为仅输出一遍,这时候无论哪组级联都使用同一个函数,他们根据调用时输入的DropDownList.ClientID来区分。
又有一天,你决定把这组级联封装为一个UserControl,做起来当然还是复制粘贴大法,也就是把3个DropDownList和JavaScript复制进UserControl,然后把UserControl的引用复制回原本的调用处。忙完之后,发现那个有两个日期输入的页面又出错了,原来updateDateRange(yearControlClientId, monthControlClientId, dateControlClientId)又被重复输出了,因为页面上放入了两个UserControl所以JavaScript被输出了两遍,并且没办法减少输出次数。 http://www.knowsky.com 这时候你能使用Page.ClientScript.RegisterClientScriptBlock解决问题,他通过type和key这两个参数确定脚本是否被重复注册,而被重复注册的脚本仅会输出一次。为什么要type和key两个参数呢?以前ASP.NET 1.x的同类函数只有key一个参数,这带来的问题是可能两个不同的控件设计时都使用了同一个key来注册自己的脚本,结果其中一个控件脚本的成功输出必然会抑制另一个控件脚本的输出。加上了type参数,各控件都用自己的类型作为标识,这样就能有效避免注册时冲突。
为何无法真正避免冲突
关于这个问题,我们先看看ASP.NET内部定义的JavaScript是以什么方式命名的。通常,private的全局函数或变量,命名都以双下划线开头,例如大家熟悉的__doPostBack,或是WebPartManager在客户端使用的__wpm。而public或protected的全局函数或变量,一般就似乎C#那样使用Pascal命名法。具体的例子,大家能用Reflector看看System.Web.UI的资源中的那些js文件。
我们暂时就假设这种命名法是正确的,然后模仿着去在自己研发的控件中实践。事实上非常多控件研发者也确实这样做了,比较多的专业控件中你都能看到双下划线开头命名的函数或变量,这至少能避免和控件使用者在页面上注册的函数或变量冲突,因为在页面上注册的函数或变量通常都采用比较简单的命名法。
如果目前我们要做一个浮动上下文菜单,也就是当你的鼠标移动到某个HTML元素上时该浮动菜单自动出现,当鼠标离开元素并且也不在菜单上时,菜单自动消失。为了方便用户操作,我们允许用户鼠标移动过程中稍微离开菜单区域,所以定义当鼠标离开菜单区域若干时间后才让菜单消失,而这个时间在客户端保存在__disappearAfter变量中。这个控件看起来什么问题都没有,直到你把他和ASP.NET 2.0自带的Menu控件放在同一个页面上,因为Menu控件也有类似的功能,而且和我们的控件相同Menu控件选择了将时间变量保存在一个名为__disappearAfter的变量中。
现然,作为ASP.NET框架的使用者,框架没有声明这个变量的名字不允许使用,我用了有问题当然就能认为是框架的错。Brad Abrams写了一本《.NET设计规范/Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries》,里面却完全没有提及JavaScript和CSS的规范,似乎在ASP.NET中使用到的JavaScript和CSS都是琐碎的不能在琐碎的事情,所以完全不值得一提。
事实上,既然ASP.NET允许一个页面上不同的控件设计者引入不同的JavaScript和CSS,就必须提供一种方法去管理潜在的命名冲突。如果是JavaScript,我们能考虑使用ASP.NET AJAX的namespace来避免冲突,下一代代号为Orcas的Visual Studio和ASP.NET将内置ASP.NET AJAX支持,所以其内置控件所使用的JavaScript应该也会有namespace,这样就有有效降低冲突概率。至于CSS命名冲突,暂时没有好的解决放案,只能依赖控件设计者的习惯了,你能考虑为你的控件根元素附上一个namespace以示区分,这样也算是降低冲突概率的一个办法。
相关文章推荐
- ASP.NET 无法确保在注册的 JavaScript 内不存在重复定义
- 错误与修复:ASP.NET无法检测IE10,IE11,导致_doPostBack未定义JavaScript错误,恒处于F5卷动条位置
- 错误与修复:ASP.NET无法检测IE10,导致_doPostBack未定义JavaScript错误,恒处于FF5卷动条位置
- 错误与修复:ASP.NET无法检测IE10,导致_doPostBack未定义JavaScript错误,恒处于FF5卷动条位置
- 错误与修复:ASP.NET无法检测IE10,导致_doPostBack未定义JavaScript错误,恒处于FF5卷动条位置
- 错误与修复:ASP.NET无法检测IE10,导致_doPostBack未定义JavaScript错误,恒处于FF5卷动条位置
- 无法向会话状态服务器发出会话状态请求请。确保 ASP.NET State Service (ASP.NET 状态服务)已启动
- asp.net 实现QQ在线聊天程序中javascript的窗口注册机制
- 编译ASP.NET时,提示“请确保此代码文件中定义的类与“inherits”属性匹配,并且该类扩展的基类(例如Page 或UserControl)是正确的。
- 无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动 解决方案
- asp.net注册Javascript的方法
- asp.net 该目录不存在或因为安全设置而无法访问
- asp.net站点从2003服务器迁移到2008服务器出现定义了重复的“system.web.extensions/scripting/scriptResourceHandler”节的问题解决
- Asp.Net JavaScript使用技巧精萃
- 无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动,并且客户端端口与服务器端口相同。如果服务器位于远程计算机上,请检查。。。
- asp.net中的服务器端控件 textbox 设为只读属性后无法获取 javascript给其赋的值
- 在iis中注册asp.net 2.0 解决打开aspx文件提示无法找到该页
- 无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动 解决办法
- [Web]不同的javascript 在ASP.NET中的注册方法