阿不

用勤奋寻找未来

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  181 随笔 :: 0 文章 :: 2308 评论 :: 75 引用

         无刷新转页面? 这是我前些天提出一个想法。为什么会有这样的想法呢?主要是考虑到目前如果使用Atlas作开发的话,那就不可以避免的要下载它的脚步库。一般情况下,我们都会下载的是Atlas.js(少数情况才会下载AtlasRuntime.js),这个文件就要238KB,如果是Debug版本的程序的话,那么将会下载Debug版本的Atlas.js,而这个文件就要360KB。(所以要发布asp.net程序时,设置web.config的debug="false"很重要的.)再得寸进尺点,原来每次转页面时,都需要重新下载所以有CSSJSImage,更新ViewState等等,这些都需要花费非常多的资源和时间(可以通过Fiddler查看一下访问一次页面的过程)。那么,是不是有一种办法,做到既可以改变页面的功能,又可以不重新刷新页面呢?这样效率那该提高多少啊?

         不用框架页面,那就尝试使用动态加载用户控件的方式吧。主要思路是这样的,把原来做在页面上功能封装到一个用户控件去,利用导航菜单来动态加载不同的用户控件。由于大部分情况下,页面的框架基本都是一样的,不同的功能页面也就是部份内容的不同,和执行不同的功能而已。这就是给这样的思路提供了一个前提环境条件,做一个页面(功能类似一个MasterPage),在这个页面上做好页面总体布局,在需要动态改变的位置上放一个PlaceHolder,用Atlas UpdatePannel包起来,设置合适的更新条件刷新这块区域的内容。

         简单来看一下实现步骤。新建一个Web Site工程,创建三个不同功能的WebUserControl,在Default.aspx页面上放一个Menu控件做导航,利用它的MenuItemClick事件作导航,而不要直接设置NavigateUrl属性。 

       在页面的合适位置上放一个asp:PlaceHolder 控件,将它包含在atlas:UpdatePanel里面,设置好EventTrigger,作为这部份的刷新条件:

 

    接下来就如何动态加载UserControl的问题了,动态加载UserControl需要注意的一些细节在这篇文章里(Asp.Net中页面运行时动态载入的UserControl内元素的事件处理的注意事项)已经一个很好的讨论了。我的做法重写CreateChildControls方法,然后在这个方法里动态加载用户控件。但是还需要解决一个问题,如何才能知道要加载哪个用户控件呢?因为根据页面的事件模型,控件的处理事件是在页面加载,处理完后才被处理的,也就Menu1_MenuItemClick事件是晚于CreateChildControls方法被执行的。那在CreateChildControls方法怎么才知道要加载的控件的呢?那么如果能在这个方法中得到引发页面回发的事件源和参数就可以解决了。经过调试和查看Page类的源代码,发现有在Page类中有这两个常量定义,postEventArgumentID  (值为"__EVENTARGUMENT")postEventSourceID(值为: "__EVENTTARGET")既然有这两个常量定义,肯定也可以得到它们的请求值,最终找到了可以在Request.Form取到他们的值,而且也是我希望的值。来看看页面代码:

 

         不是很复杂的代码,应该能一看就明白了。这里就不再浪费篇幅了。

         总结:通过这种方法来改变页面功能的好处是,可以大大减少加载页面的时间,减小服务器的压力。但是可能还有很多我没有考虑到的问题会出现。希望能有一个讨论的结果。另外,在加载用户控件的部分前面,由于前面没有看到那两个常量,使用了另一种方法,但是当从一个UserControl转到另一个UserControl时,新的UserControl的第一次回发事件将不会被执行,这个问题一直没能解决。在附下载的例子中的default.aspx就还存在这样的问题,找到问题的起因,但是一直没能明白过来。

    CODE

阿不 http://hjf1223.cnblogs.com
posted on 2006-06-20 12:34 阿不 阅读(9040) 评论(69)  编辑 收藏 网摘 所属分类: JavaScript相关技术

评论

#1楼 2006-06-20 12:44 萧远山      
页面少还好办,页面一多就麻烦了。
动态加载进来本来就是在当前页,和“页面跳转”无关系~

  回复  引用  查看    

#2楼[楼主] 2006-06-20 12:51 阿不      
@萧远山
是的,所以加上引号呀。至于页面少好办,页面多就麻烦,我认为不会。因为加载的条件仍然是用户控件路径,还可以是加"~/"的。


另外一点没有考虑到,就是传值的问题。再好好想想。

  回复  引用  查看    

CSS,JS,image在客户端都被缓存啊
  回复  引用    

#4楼[楼主] 2006-06-20 13:04 阿不      
@办公平台
按理说,应该是会被缓存的。
不过我比较担心的是像Atlas(WebResource.axd?d=pUiTgJuMBKPmj1TXrtZVWqE37spx67XVvThWJVRAuw54k0nGnP2yp6ZhRZYQzwU_BpjNNDp_cjgXj0rFQDxNo4298Wlc1gOQR_MSDzzB0bA1&t=632800233360000000)这种直接从程序集下载的js代码会不会被缓存?从Fiddler 观察的结果来看是有的,如下:
HTTP/1.0 Expires Header is present: Mon, 28 Aug 2006 10:39:36 GMT
HTTP/1.1 Cache-Control Header is present: public
但是我也发现大部分的请求的Caching选项要么是
HTTP/1.1 Cache-Control Header is present: private
要么就是空的。

  回复  引用  查看    

#5楼 2006-06-20 14:30 浪子      
@阿不

在想入深点,就是一个简单的Web.MVC模式具体实现:)

目前我的框架正是这种思想.

关于你的传值,可以通过构建一个页面共享单间实例就可以实现任意对象的传递.

  回复  引用  查看    

#6楼[楼主] 2006-06-20 14:36 阿不      
@浪子
对MVC模式还没有更深理解和体会,这只是我的一个想法。

另外,对传值的问题确实有很多的解决办法,等到实际问题的时候再寻找一种合式的解决方案。

  回复  引用  查看    

#7楼 2006-06-20 14:37 大力      
我怎么看得页面很乱,是我的浏览器有问题还是这个页面CSS有问题呀?
  回复  引用  查看    

#8楼[楼主] 2006-06-20 14:46 阿不      
@大力
不会呀,我在IE和Firefox都可以正常显示的。

  回复  引用  查看    

#9楼 2006-06-20 17:21 苍冥      
全都只是在当前页显示,并不是页面跳转.如果页面多的话处理比较麻烦,如果刷新的话会回到初始状态,所以还得处理状态的保存
  回复  引用  查看    

#10楼[楼主] 2006-06-20 17:38 阿不      
@苍冥
我一直都不理解为什么样页面多处理会比较麻烦,这种方式下,仍然像原来那样子做链接,只不过是链接的时候是链接用户控件,然后对它进行处理。

是的,刷新的话,确实会回到初始状态,但是我们可以控制不让用户刷新页面,让它使用我们提供了用刷新功能。

  回复  引用  查看    

支持一下,想法不错!
  回复  引用    

#12楼[楼主] 2006-06-20 20:13 阿不      
@ 冲凉不除3
谢谢^_*

  回复  引用  查看    

不错
  回复  引用    

#14楼 2006-06-21 15:39 fansvip[未注册用户]
这种方式不方便缓存
  回复  引用    

#15楼[楼主] 2006-06-21 17:00 阿不      
@fansvip
所谓的缓存是指?页面缓存?

  回复  引用  查看    

#16楼 2006-06-22 08:43 abc111[未注册用户]
一个页面也是一个类,
一个类有所为有所不为,
楼主说的是技巧性太强的东西,其实不利于oo,代码管理

  回复  引用    

#17楼[楼主] 2006-06-22 09:30 阿不      
@abc111
确实有点取巧的感觉.:)
不过在这里,就不把页面当成普通的页面的了,而充当了是MasterPage的角色了.

  回复  引用  查看    

#18楼 2006-06-22 09:31 浪子      
@阿不
我也是慢慢在学习...
有空多交流.你的MSN?

  回复  引用  查看    

#19楼[楼主] 2006-06-22 09:35 阿不      
@浪子
我的博客园ID加上hotmail.com

  回复  引用  查看    

#20楼 2006-06-22 09:51 Victor1[未注册用户]
用户没法记下当前的网址

搜索引擎没法收录...


  回复  引用    

#21楼[楼主] 2006-06-22 09:57 阿不      
@Victor1
是的,这是所以无刷新应用都可能存在的问题。我们这样做也是有一定的应用场合的,如果是一个管理程序,就不存在被搜索的必要了,而且还有尽量避免被搜索的。

  回复  引用  查看    

#22楼 2006-06-22 10:16 Victor1[未注册用户]
不知道你有没有用过Gmail, 它是无刷新的,
不是知道它的技术能不能被搜索引擎收录
但是它可以通过IE的后退来回来以前的页面,想必是可以记下网址的。

  回复  引用    

#23楼 2006-06-22 10:20 Victor1[未注册用户]
你说的没错,现在无刷新的应用一般都在不需要搜索引擎收录的情况下。

无刷新很好,但却不能被广泛利用,实在是可惜

  回复  引用    

#24楼[楼主] 2006-06-22 10:27 阿不      
@Victor1
Gmail天天在用,在转页面的时候地址是没有变的,但似乎它的整个页面都会刷新一下(有点快,看不出来)。
它确实做得很好,通过IE的后退按钮就可以退回去,这点我想需要好好研究一下人家是怎么做的。
至于搜索引擎方面,想想google是什么出身的?不过我想Gmail的搜索应该不同一般的网页搜索的。

  回复  引用  查看    

#25楼 2006-06-22 11:08 浪子      
@阿不
其实你的想法,通过动态载入UserControl的方法,也是可以通过后退回到上一个View(我把每一个UserControl 称为一个WebView)的.
IE的后退其实读的是本地缓存.而当你动态载入View的时候,本地缓存同样在做.

不过我现在的页面不是真正的无刷新,只能说无跳转(转化为View的动态切换),我在View的切换的时候还是要刷新的.

  回复  引用  查看    

#26楼[楼主] 2006-06-22 11:30 阿不      
我现在是用两个堆栈来记录前进和后退的历史记录的。并且自己提供前进和后退按钮来做导航功能,如果能直接使用IE的前进和后退事件,并调用这两个栈那就最好了。
  回复  引用  查看    

#27楼[楼主] 2006-06-22 11:32 阿不      
我刚才也试了一下,确实可以用IE的后退按钮(UpdatePanel的功劳了),并且一样的载入前一个用户控件。但是页面会刷新就是了。而我上面的方法就不会刷新
  回复  引用  查看    

#28楼[楼主] 2006-06-22 11:40 阿不      
错了错了,刚才有两个操作是有刷新的,所以IE的后退按钮有效。上面的结论有误!
  回复  引用  查看    

#29楼 2006-06-22 12:09 Victor1[未注册用户]
to 浪子

在我这里后退按扭一直都是灰色的

to 阿不

可以上MSN,交流一下吗

  回复  引用    

#30楼[楼主] 2006-06-22 12:28 阿不      
@ Victor1
在公司不用装MSN,也不能上,下班时间交流吧。

  回复  引用  查看    

#31楼[楼主] 2006-06-22 13:07 阿不      
标记一下:新加载的用户控件中的按钮事件第一次不执行的原因已经找到了。
http://wljcan.cnblogs.com/archive/2004/06/14/15604.html">http://wljcan.cnblogs.com/archive/2004/06/14/15604.html

太及时了,正卡在这边!

  回复  引用  查看    

#32楼 2006-06-22 14:08 浪子      
@Victor1
那可能你的是真正的无刷新.

我的系统架构并不是无刷新,我的只是无页面跳转 :)

我觉得现在还没有即简单又稳定的Ajax框架可以支撑整个系统的无刷新,不想加大开发的难度,毕竟平时的工作已经蛮紧张了:) 偷懒一下,等有了成熟体系之后再加入

只要有刷新IE就有缓存,就可以后退.

你整个页面都没有刷新过,自然没有后退 :)

  回复  引用  查看    

#33楼[楼主] 2006-06-22 15:53 阿不      
@浪子
准确点说,应该是部分刷新,我是利用Atlas的UpdatePanel,把动态加载用户控件的那部分内容做成部分刷新的。经过一些处理后,开发难度根本就不会加大,倒是认为某些方面更加简单了(个人认为),改天有空把成形的结构做成一个完整的例子。至于整个页面确实是无刷新的,完全就是在用户控件中跳转。

  回复  引用  查看    

#34楼 2006-06-22 16:31 浪子      
@阿不

UpdatePanel 你在项目中启用过了嘛?运行稳定不?

看到园里的朋友讲的showcase,显然有些不稳定~~~~怕怕

等大家都认可的时候再引入项目中....呵呵

我比较怕影响项目的进度和运行稳定性

  回复  引用  查看    

#35楼[楼主] 2006-06-22 17:46 阿不      
不会啊,现在这个版本还是可以的,UpdatePanel已经相对比较稳定了。不过倒是那套AtlasToolKit确实很不稳定。我从1月份的CTP开始用的(好像是吧,记不得了),那时候确实有些问题,不过现在好多了。Atlas也已经快三个月没有发新版本了,以前都是每个月一个版本的,说明什么?说明已经没有太致命的BUG了吧。应该是,个人看法。至少我的项目一直在用atlas,虽然还不稳定。
  回复  引用  查看    

#36楼 2006-06-22 23:47 大剑师      
还是用Iframe吧,用Updatepanel加载UserControl?!恐怕平添无数烦恼 算了不说了
  回复  引用  查看    

#37楼[楼主] 2006-06-23 08:37 阿不      
@ 大剑师
您是不是担心UpdatePanel与其它控件的协作呀?我也有这点担心,以前就有遇到过不兼容的情况。先试再说吧,如果能行就非常棒了。

  回复  引用  查看    

#38楼 2006-07-03 14:18 大剑师      
@阿不
是阿,至少我使用时有无数的问题,特别是,你的控件中使用JS的情况!除了即时写到流中,注册到页面中是行不通的,因为页面没有刷新!只是在客户端动态修改了Div的InnerHTML属性,复杂的控件肯定有问题的。

  回复  引用  查看    

#39楼[楼主] 2006-07-03 17:22 阿不      
@大剑师
我之前有做过几个简单的测试,大部分问题都能得到解决,至少目前还没有特别影响我的问题存在。至于你说的控件使用js的情况?是不是说在我们自己写的控件里无法内部注册js函数?如果我的理解是正确的话,那么应该是有办法的,我就写过从GridView继承下来的控件,在里面使用过js代码。

  回复  引用  查看    

#40楼 2006-07-06 19:21 刘誉儿      
我是使用MutliView来处理,不同的跳转其实都在一个页面,只不过放在不同的view里,感觉也不错。
然后把MutliView放在UpdatePanel中


  回复  引用  查看    

#41楼[楼主] 2006-07-06 22:07 阿不      
@ 刘誉儿

那样的话,比较有限,而且做起来限制也相对比较多.

  回复  引用  查看    

#42楼 2006-07-20 15:32 荣[未注册用户]
无刷新的用户控件要怎么做啊?
  回复  引用    

#43楼[楼主] 2006-07-20 18:57 阿不      
@荣
用户控件本身并不需要无刷新。

  回复  引用  查看    

你好,大大的程式确实可行,
容小弟问一下,
如果遇到那种按下按钮之后处理完要换页的,应该要怎么办呢?

例如使用者注册完,想把他带到另外一页去,
该怎么做呢?

小弟直接在该事件之后加入javascript ,
Page.ClientScript.RegisterStartupScript(GetType(), \"errorg\", \"<script type=\'text/javascript \'>__doPostBack(\'Menu1\',\'main.ascx\');</script>\");
似乎无法正常运作呢.

不过
Page.ClientScript.RegisterStartupScript(GetType(), \"errorg\", \"<script type=\'text/javascript \'>alert(\'test\');</script>\");
却可以预期的弹跳出警告视窗.

大大有解决的方法吗?

  回复  引用    

抱歉,程式转换出现一堆斜线...
  回复  引用    

#46楼[楼主] 2006-07-29 22:43 阿不      
@kkentlai
你是想说什么呢?RegisterStartupScript方法是注册马上运行的js函数?但你调用的是__doPostback方法呀,能不能正确运行我确实不大清楚,另外我上面的代码只是一个比较粗糙的想法,如果要深入应用,还需要在不断加工,解决一些问题,不过我目前已经在使用这样的方案了,还没有遇到致命的问题。

  回复  引用  查看    

那请问大大您的作法,
例如说访客登出,
目前访客位於需要登录才能观看的页面,
左边有个linkbutton,按下去之后会执行事件,
此事件将访客的cookie给删除,然后出现个告示说已经登出,
(目前这边运行无误)

接下来才是问题,
因为是无刷新的关系,右边目前还是在需要登录才能观看的页面,
想做到不管在哪一页登出,
右边都会跑到首页去.

不知道大大会如何处理这样的问题呢.
感恩回答.

  回复  引用    

#48楼[楼主] 2006-07-29 23:17 阿不      
@kkentlai
首先,“大大”是什么样的称呼呢,还是请不要使用这样的称呼,我也是一个学习者。
另外,你所提到的问题与本主题没有很直接的联系,建议你可能去看看asp.net的验证和授权机制,我想对你会有很大的帮助的。

  回复  引用  查看    

小弟似乎有点复杂化了,那简单一点说好了,

在右边的ascx页面中,
可以在事件中直接做到转换页面吗?

小弟是这样写的,
protected void loginbtn_onclick(object sender, EventArgs e)
{
PlaceHolder1.Controls.Clear();
ControlType = "model/member/reg.ascx";
ITemplate m_template = Page.LoadTemplate(ControlType);
m_template.InstantiateIn(PlaceHolder1);
}

不过似乎没有反应耶.
感谢回答.

  回复  引用    

#50楼[楼主] 2006-07-29 23:35 阿不      
没有提示出错吗?具体我也不清楚什么问题啊,你可以好好调试一下。可能是有些地方不合适吧。
  回复  引用  查看    

有个看似蛮严重的小问题...
请问该如何初始第一次进入时要做的事情呢?
(在这里是指按下左边的Menu1,载入右边的UserControl控件时,
UserControl控件开做的初始)
if (!IsPostBack)
{
test3.Text = \"1\";
}
else
{
test3.Text = \"2\";
}

第一次进去出现2,
按下该页面中的按钮post回去,
还是出现2,代表没有初始化.


  回复  引用    

#52楼[楼主] 2006-07-31 08:20 阿不      
你把程序发给我,我帮你看一下。
  回复  引用  查看    

aspx档案:
<asp:literal id="selectvalue" runat="server" />
<table width="350" align="center" cellpadding="3" cellspacing="0">
<tr>
<td>年</td>
<td><asp:DropDownList ID="myear" runat="server"> </asp:DropDownList>
</td>
</tr>
<tr>
<td colspan="2"><asp:Button ID="saveButton" runat="server" Text="储存" OnClick="saveButton_Click"></asp:Button></td>
</tr>
</table>

后置:
public partial class model_member_info : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
//判断年
for (int i = 1960; i < DateTime.Now.Year; i++)
{
ListItem y = new ListItem();
y.Text = i.ToString();
y.Value = i.ToString();

//使1980等於预设
if (i == 1980)
{
y.Selected = true;
}
myear.Items.Add(y);
}
}

protected void saveButton_Click(object sender, EventArgs e)
{
selectvalue.Text = myear.SelectedValue;
}
}
小弟是要让对方选择其他的年,但每次按下saveButton,
都只会抓到1980,无法正确的抓到使用者所选的东西.

  回复  引用    

再问一下,要怎么执行if (!IsPostBack){}里面的东西呢?
有些东西我想初始化,
但输入进入if (!IsPostBack){}里面,
都不会去执行说.

  回复  引用    

#55楼 2006-09-06 18:40 laue[匿名]
你好
你有没有遇到过这样动态加载的控件中如果有gridview
gridview的rowcommand事件不能触发的情况?

  回复  引用    

#56楼[楼主] 2006-09-06 21:32 阿不      
@ laue[匿名]
不会出现这种情况吧?一种可能是你动态绑定RowCommand事件吧?

  回复  引用  查看    

你好,我的发现在用户自定义控件中按钮的js事件不能执行,会出错,在动态加载js的情况不会出错,但不执行
  回复  引用    

#58楼[楼主] 2006-10-24 12:51 阿不      
@几米天空
你可以在OnPreRender事件下使用Page.ClientScript.RegisterClientScriptInclude函数注册js文件。

  回复  引用  查看    

@阿不
谢谢了。。可以。
呵呵。。后面可能还有其他问题。

  回复  引用    

@阿不
刚又发现一个问题,在视图(UserControl)中有个按钮是弹出新建记录的页面,新建完后要进行返回,那怎么通过模态窗口返回值进行刷新这个视图里的GridView??

  回复  引用    

#61楼[楼主] 2006-10-24 15:06 阿不      
@几米天空
使用模态窗体,你就必须刷新页面了。你可以使用SuBModal,利用它模拟模态窗体,在返回时触发PostBack事件(如何触发浏览http://www.cnblogs.com/hjf1223/archive/2006/07/05/443761.aspx">http://www.cnblogs.com/hjf1223/archive/2006/07/05/443761.aspx)更新父窗体内容。

  回复  引用  查看    

原来的思路是利用隐藏的textbox,由模态窗口的返回值触发它的OnTextChanged事件,竟然也要鼠标触发。。
谢谢了。。我先去看下。

  回复  引用    

#63楼 2006-10-25 08:41 几米天空      
对了,用SubModal在视图中好像不行,因为涉及到复式控件问题,脚本运行出错。
  回复  引用  查看    

#64楼[楼主] 2006-10-25 13:30 阿不      
@ 几米天空
我给你留言了,有什么问题我们在MSN上或通过Email交流。

  回复  引用  查看    

#65楼 2006-12-10 22:38 Cat Chen      
其实不用抢阶段来操作的,结合ChildControlsCreated和EnsureChildControls就在控件事件出发阶段才加载子控件。我在这帖里回复你时详细解释了:
http://www.cnblogs.com/cathsfz/archive/2006/12/10/587925.html">http://www.cnblogs.com/cathsfz/archive/2006/12/10/587925.html

  回复  引用  查看    

在线汉语词典 http://www.***
  回复  引用    

登陆界面登陆进入主界面以后,在浏览器上还可以点后退,返回到登陆页面,怎么能让他不回后退
email:salonliudong@163.com
MSN:liuzidong88@hotmail.com
QQ:278104696

  回复  引用    

#68楼[楼主] 2007-05-14 08:30 阿不      
那个肯定是可以后退的,IE在每次访问一个新页面都会有历史记录的。
  回复  引用  查看    

#69楼 2007-06-27 11:43 qq[未注册用户]
@萧远山
tongyi

  回复  引用    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 430475




相关文章:

相关链接: