zoukankan      html  css  js  c++  java
  • [原创]ExtAspNet秘密花园(十) — Ajax特性

    为了深入理解ExtAspNet的Ajax特性,我们还是先来看看Asp.Net中的回发机制,继而讲解ExtAspNet是如何对此回发过程进行改造,来实现ExtAspNet所特有的原色Ajax。

     

    Asp.Net的回发机制

    简单说来,Asp.Net的回发过程是这样:首先服务器将服务器端控件渲染为HTML返回给浏览器,当用户进行某项操作时,通过表单提交的方式将控件相关数据提交到服务器,然后在服务器端恢复控件状态并触发相应事件。

    在Asp.Net中有两种表单的提交方式:

    1. 通过type="submit"的默认表单提交

    下面来看一个简单的示例:

    ASPX页面:

       1:  <form id="form1" runat="server">
       2:      <asp:Button ID="Button1" runat="server" Text="Button1"  OnClick="Button1_Click">
       3:      </asp:Button>
       4:  </form>
    生成的HTML标签为:
       1:  <html>
       2:      
       3:      <head>
       4:          <title></title>
       5:      </head>
       6:      
       7:      <body>
       8:          <form name="form1" method="post" action="textbox.aspx" id="form1">
       9:              <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMjA0…6y+e3Tou1Yo="
      10:              />
      11:              <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAgL…PagKn2HgW"
      12:              />
      13:              <input type="submit" name="Button1" value="Button1" id="Button1" />
      14:          </form>
      15:      </body>
      16:   
      17:  </html>

    点击Button1提交表单时,HTTP请求参数如下所示:

    image

    回顾整个过程,表单提交是通过点击提交按钮(type=submit)触发的,在HTTP请求参数中我们发现Button1=Button1,这个参数是浏览器的默认添加的。服务器端也正是根据这个参数来找到点击了那个控件,并触发相应的服务器端事件的。

    2. 通过JavaScript控制的表单提交

    我们对上面的示例稍作修改:

    ASPX页面:

       1:  <form id="form1" runat="server">
       2:      <asp:Button ID="Button1" runat="server" Text="Button1"  UseSubmitBehavior="false" OnClick="Button1_Click">
       3:      </asp:Button>
       4:  </form>

    生成的HTML标签为:

       1:  <html>
       2:  <head><title></title></head>
       3:   
       4:  <body>
       5:      <form name="form1" method="post" action="textbox.aspx" id="form1">
       6:   
       7:      <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
       8:      <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
       9:      <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMjA0…e3Tou1Yo=" />
      10:   
      11:  <script type="text/javascript">
      12:  //<![CDATA[
      13:  var theForm = document.forms['form1'];
      14:  if (!theForm) {
      15:      theForm = document.form1;
      16:  }
      17:  function __doPostBack(eventTarget, eventArgument) {
      18:      if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
      19:          theForm.__EVENTTARGET.value = eventTarget;
      20:          theForm.__EVENTARGUMENT.value = eventArgument;
      21:          theForm.submit();
      22:      }
      23:  }
      24:  //]]>
      25:  </script>
      26:   
      27:      <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAgLlxsf1…wCPagKn2HgW" />
      28:   
      29:      <input type="button" name="Button1" value="Button1" onclick="javascript:__doPostBack('Button1','')" id="Button1" />
      30:      </form>
      31:  </body>
      32:  </html>

    点击Button1提交表单时,HTTP请求参数如下所示:

    image

    虽然两次得到的结果一致,但是第二个示例是通过JavaScript来提交表单的。服务器端根据HTTP请求中__EVENTTARGET的值来找到回发的控件,并触发相应控件的服务器端事件。

    太棒了太棒了太棒了

    ExtAspNet特有的Ajax处理机制

    我们都知道ExtAspNet的所有控件行为都是默认AJAX的,那个ExtAspNet是如何做到的呢?

    其实道理也简单,你可以打开ExtAspNet的源代码,找到js/X/X.ajax.js文件。我们会发现如下的代码:

       1:  X.ajax = {
       2:      hookPostBack: function () {
       3:          if (typeof (__doPostBack) != 'undefined') {
       4:              __doPostBack = x__doPostBack;
       5:          }
       6:      }
       7:  };
       8:   
       9:  function x__doPostBack(eventTarget, eventArgument) {
      10:      if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
      11:          theForm.__EVENTTARGET.value = eventTarget;
      12:          theForm.__EVENTARGUMENT.value = eventArgument;
      13:   
      14:          Ext.Ajax.request({
      15:              form: theForm.id,
      16:              url: document.location.href,
      17:              success: function (data) {
      18:                  // ....
      19:              },
      20:              failure: function (data) {
      21:                  // ...
      22:              }
      23:          });
      24:      }
      25:  }

    在页面初始化时,我们会调用X.ajax.hookPostBack,此函数内使用x__doPostBack函数来覆盖页面生成的__doPostBack函数,这样原本所以对__doPostBack的调用都进入我们自己定义的处理函数中。在x__doPostBack处理函数中,我们不是调用表单的submit函数,而是调用Ext.Ajax.request来发起一次Ajax请求。

    简单来说,就是首先拦截__doPostBack函数,然后调用Ext.Ajax.request,是不是很简单。

    问题来了

    我们介绍了Asp.Net的两种回发机制,其中第二种使用的正是__doPostBack函数,但是第一种却依赖于浏览器对type=submit的默认处理行为。这也导致在页面中使用正常Asp.Net的Button,不会有ExtAspNet所特有的AJAX行为,怎么办?

    由于我们无法修改Asp.Net控件的实现代码,也不可能向每个使用者传授UseSubmitBehavior=false的小技巧,我们希望使用ExtAspNet的开发者能够不假思索地快速开发,而不是陷在Asp.Net所设置的陷阱中。怎么办?

    迎刃而解

    困难是难不倒我们这些勤劳善良的程序员,让我来略施小技:

    既然无法控制第一种提交方式,我们就来将其改造为第二种方式怎么样:

       1:  makeAspnetSubmitButtonAjax: function (buttonId) {
       2:      function resetButton(button) {
       3:          button.set({
       4:              "type": "button"
       5:          });
       6:          button.addListener("click", function (event, el) {
       7:              __doPostBack(el.getAttribute("name"), "");
       8:              event.stopEvent();
       9:          });
      10:      }
      11:   
      12:      if (typeof (buttonId) === "undefined") {
      13:          Ext.each(Ext.DomQuery.select("input[type=submit]"), function (item, index) {
      14:              resetButton(Ext.get(item));
      15:          });
      16:      } else {
      17:          var button = Ext.get(buttonId);
      18:          if (button.getAttribute("type") === "submit") {
      19:              resetButton(button);
      20:          }
      21:      }
      22:  }

    同时ExtAspNet还提供了一个参数来关闭这种行为,它就是PageManager的EnableAspnetSubmitButtonAjax属性。

    从这个小地方也体现了ExtAspNet细致入微、精益求精的态度,致力为广大开发者打造一个方便快捷的Asp.Net控件库。

    ExtAspNet和AspNet的按钮同时出现的示例

    你可以在线查看这个示例的运行效果,其界面截图如下所示:

    image

    ASPX的页面标签非常清晰:

       1:  <ext:PageManager ID="PageManager1" AjaxAspnetControls="aspBox,aspButton" runat="server" />
       2:  <ext:ContentPanel ID="ContentPanel1" runat="server" Width="500px" BodyPadding="5px" EnableBackgroundColor="true" ShowBorder="true" ShowHeader="true" Title="内容面板">
       3:      <ext:TextBox runat="server" Width="300px" ID="extBox"></ext:TextBox>
       4:      <asp:TextBox runat="server" Width="300px" ID="aspBox"></asp:TextBox>
       5:      <ext:Button ID="extButton" runat="server" CssClass="inline"
       6:      Text="ExtAsp.Net 按钮" OnClick="extButton_Click"></ext:Button>
       7:      <asp:Button ID="aspButton" Text="Asp.Net 按钮" runat="server"
       8:      OnClick="aspButton_Click" />
       9:  </ext:ContentPanel>

    这里有两个应用技巧:

    1. 除非放在最外层的<form>标签里,否则Asp.Net的标签必须放在ContentPanel中。

    2. 通过AjaxAspnetControls属性来定义需要在回发是更新的Asp.Net控件,这个特性在《ExtAspNet秘密花园(四) — 每个页面需要一个PageManager》有详细的描述。

    后端的C#代码没有任何特殊的地方:

       1:  protected void extButton_Click(object sender, EventArgs e) {
       2:      aspBox.Text = "Asp.Net 输入框 - " + DateTime.Now.ToLongTimeString();
       3:      extBox.Text = "ExtAsp.Net 输入框 - " + DateTime.Now.ToLongTimeString();
       4:      aspButton.Text = "Asp.Net 按钮 - " + DateTime.Now.ToLongTimeString();
       5:      extButton.Text = "ExtAsp.Net 按钮 - " + DateTime.Now.ToLongTimeString();
       6:  }
       7:   
       8:  protected void aspButton_Click(object sender, EventArgs e) {
       9:      aspBox.Text = "Asp.Net 输入框 - " + DateTime.Now.ToLongTimeString();
      10:      extBox.Text = "ExtAsp.Net 输入框 - " + DateTime.Now.ToLongTimeString();
      11:      aspButton.Text = "Asp.Net 按钮 - " + DateTime.Now.ToLongTimeString();
      12:      extButton.Text = "ExtAsp.Net 按钮 - " + DateTime.Now.ToLongTimeString();
      13:  }

    至此,整个示例就完成。没有任何让人感到突兀的地方,而Asp.Net的按钮控件却自动拥有了ExtAspNet的AJAX特性。

    小结

    本章可以明显看出ExtAspNet的对细节的追求和微创新,首先是对__doPostBack函数的拦截来实现Ajax,从而保证Asp.Net的默认调用方式不变,也为方便的切换Ajax与传统的页面回发埋下了伏笔;其次对于type=submit的按钮,ExtAspNet通过PageManager的EnableAspnetSubmitButtonAjax属性来将其转化为第一种方式,从而保证了ExtAspNet的Ajax在所有情况的通用性。

    下一篇文章,我们开始讲述页面中布局的使用,布局是用好ExtAspNet的关键,也是Asp.Net缺失的一个环节,所以不大容易理解,需要大家认真对待。

    注:《ExtAspNet秘密花园》系列文章由三生石上原创,博客园首发,转载请注明出处。文章目录 官方论坛

  • 相关阅读:
    SQLSERVER查询整个数据库中某个特定值所在的表和字段的方法
    asp.net core 2.0 Json结果的格式
    Lambda表达式怎么写SQL中的in?
    jq中append()、prepend()、after()、before()的区别
    C#发送电子邮件代码记录
    Windows10系统下,彻底删除卸载MySQL
    C# DataTable 详解
    重装系统后开机时出现两个操作系统需要选择才能进入 怎样删除一个
    函数的防抖和节流
    js 实现watch监听数据变化
  • 原文地址:https://www.cnblogs.com/sanshi/p/2379271.html
Copyright © 2011-2022 走看看