在开发过程中经常可以遇到下面几个问题:
1.在web用户控件或页面经常会引入一个外部的javascript或css文件。
先说页面吧,当年我有bbs、在线客服、博客,等一些独立的系统。但突然有一天部门接了一个oa的项目,这个oa中又刚好需要bbs、在线客服、博客这些功能。那么我就在根目录下做三个文件夹分别是bbs、blog和webim。
然后直接把原来的系统放到里面去,做好接口,集成进去。
这样做看起来对网站目录的规划更合理、且这三个系统中在根目录下的文件和文件夹不会起冲突。可在页面上直接引入的js和css文件的虚拟路径就出问题了。然道一个个的去改吗?
再说web用户控,这个问题更普遍。比如有个web用户控中引用了一个css文件,可这个web用户控被好多页面引用,且这些页面有很多都不在同一目录下,然道我们每个页面都去引用一次吗?我觉得这样非常不好,css是这个web控件依赖的一个元素,而不是页面的,为什么css文件要注册到页面上呢?为什么还要受页面的路径影响呢?
当然,像“js/javascript.js”这样的路径肯定是不行。部署的时候实施大哥万一不把你的项目直接建立在网站下,而建立到虚拟目录下,那这个路径就是错的。
其实也不是实施大哥的问题,很多服务器都是有它自己的规则,由不得你。比如,我们那抠门的公司一个服务器上要部署200个网站。哪能让你随便搞啊,他说怎么样就怎么样。
2.在后台代码中注册一段弹出脚本。alert();
这个问题非常有意思,比如,你有个添加页面,添加完了后你alert一句话“添加成功!”,多好啊。
然后你又点了个超链接跳到另外个页面。刚好这个页面有个返回按钮。这个按钮直接用js回退到上一页。
结果一回退到上一页(添加页面),他自动给你弹个“添加成功!”的提示。
当时什么用cookie啊,记时间啊,都想过了。总觉得有点大才小用的感觉。
看到这里的朋友不妨自己先想想,有什么好的解决方法,然后再看下面的代码。
为了解决这两个问题,我是这么做的。
先做个IRegisterScriptClient接口。
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.HtmlControls;
namespace CE.Components.Base
{
/// <summary>
/// 提供客户端脚本注册功能的接口。
/// 分别在CE.HR.Base.PageBase和CE.HR.Base.UserControlBase两个类中实现。
/// </summary>
public interface IRegisterScriptClient
{
/// <summary>
/// 使用键和 URL 向 Page 对象注册客户端脚本包含
/// </summary>
/// <param name="key">要注册的客户端脚本包含的键。</param>
/// <param name="url">要注册的客户端脚本包含的 URL。</param>
[SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#")]
void RegisterClientScriptInclude(string key, string url);
/// <summary>
/// 向 Page 对象注册客户端Css样式包含
/// </summary>
/// <param name="url">要注册的客户端Css样式包含的 URL。</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
void RegisterClientCssStyleInclude(string url);
/// <summary>
/// 向 Page 对象注册客户端脚提示消息。
/// </summary>
/// <param name="msg">要弹出的消息。</param>
void RegisterClientScriptAlertMessage(string msg);
}
}
实现接口RegisterScriptClient.cs
2using System.Collections.Generic;
3using System.Text;
4using System.Web.UI;
5using System.Web.UI.HtmlControls;
6
7namespace CE.Components.Base
8{
9 class RegisterScriptClient : IRegisterScriptClient
10 {
11
12 private Control control;
13 private const string SCRIPT1 = "var alertMessageGuid = \"";
14 private const string SCRIPT2 = "\";if (window.name != alertMessageGuid){alert(\"";
15 private const string SCRIPT3 = "\");alertMessageGuid = window.name;}";
16
17 public RegisterScriptClient(Control control)
18 {
19 this.control = control;
20 }
21
22 IRegisterScriptClient 成员
83
84 }
85}
然后再做个页面和web用户控件的基类。这个是页面基类。
using System.Web.UI;
namespace CE.Components.Base
{
/// <summary>
/// HR系统所有页面的基类。
/// </summary>
public class PageBase : Page, IRegisterScriptClient
{
private IRegisterScriptClient scriptClient;
public PageBase()
{
scriptClient = new RegisterScriptClient(this);
}
IRegisterScriptClient 成员
}
}
这样使用起来就会方便很多。注册脚本或者样式表,可以直接使用应用程序根的虚拟路径。(例如,以“~/page.aspx”的形式)
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using CE.Components.Base;
public partial class _Default : PageBase
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
//调用框架的基类方法,可以直接使用“应用程序根的虚拟路径”注册js和css文件到页面。
this.RegisterClientCssStyleInclude("~/skin/StandardUI.css");
}
}
还有注册脚本引用和alert脚本,以及在用户控件中的使用我就不啰嗦了,一样的东西。