最近在开发网站,大量用到了用户控件,遇到了一个棘手的问题。用户控件在网站中的路径在使用中是跟随的母页的路径。由于各个页面都可能使用同一用户控件,所以其实际路径各不相同。这对引用JS/css/图片带来了困扰。
我原来的作法是:在所属页面统一加载JS/css,但是这好象不符合OO原则,增加了页面与用户控件间的耦合。于是想有没有什么其它的方法。
图片引用可以通过在页面嵌入
<%=ResolveUrl(url)%>
来解决,但js/css则不能这样。因为同一页面可能会引用不同的用户控件,不同的用户控件又可能会引用同一js/css,这会导致同一js/css在最终生成的页面上被加载多次。在网上搜了搜,有种解决方法,就是在用户控件的OnPreRender事件(或其它合适事件)内通过对Page.Header对象进行判断来决定是否加载,如果没有加载,则将"<script src='url'></script>"封装到一个literal控件内,然后将些控件加载到Header中。呵呵,好是好,就是觉得太麻烦了。后来本人想来想去,发现了一个更简单的方法:Page类内有个ClientScript类,有个RegisterClientScriptBlock方法,作用是向页面注册JS代码。那我能不能把上面这调动JS的HTML代码放进去呢。事实证明是可以的:
Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), ResolveUrl("url"), "<script src='" + ResolveUrl("url") + "'></script>;", true);
不过有几点需要注意:
1.用户控件本身是没有ClientScript类的,需要引用Page.
2.在注册类型时,是Page.GetType(),而不是一般的GetType(),原因请自行思考
3.在这里key参数是本js/css的路径,而同一页面相对于js/css的相对路径是一致的,那么即使后台注册多次,这个key值也是一致的。而所有用户控件所属的Page也是一致的,所以Page.GetType()也是一致的。type与key对于同一js/css都是一致的,那么无论后台注册多少次,前台都只会注册一次。
但是这个方法是有缺点的:
RegisterClientScriptBlock方法会在<form>标签后注册脚本,而不是头部。这样的话如果在头部写的JS需要后面JS的支持,则会报错。解决方法是遵守一个原则:谁需要,谁调用。即:用户控件只加载用户控件需要的JS/css,页面加载页面需要的JS/css,但是如果用户控件与页面都需要同一JS/css,哎~~没办法了,这就非要加载两次了