2011-11-17 30 views
10

我有一个用户控件上加载一个单独的用户控件下每个jquery选项卡。每个用户控件都是唯一的。它现在一切正常,但整体页面响应速度太慢。为了提高性能,我试图在需求下加载这些选项卡下的少量用户控件(即单击选项卡)。可能没有回帖... ajaxish。 任何人都可以引导我吗? 我试图按照this教程和this一个,但没有任何成功。我附加了父用户控件的代码。在jquery标签下按需加载usercontrols

<ul id="tabs"> 
<li class="active">Rewards</li> 
<li id="liCoupons">Coupons</li> 
<li id="liLibrary">Library</li> 
<li id="liProducts">Favorite</li> 
<li id="liPreferences">Preferences</li></ul><ul id="tabPanes" class="rewardsTabs"> 
<li> 
    <div class="wrapper active"> 
     <uc:Rewards ID="wellness" runat="server" /> 

    </div> 
</li> 
<li id="liCoupons"> 
    <div class="wrapper"> 
     <uc:Coupon runat="server" /> 
    </div> 
</li><li id="liLibrary"> 
    <div class="wrapper"> 
     <uc:Library runat="server" /> 
    </div> 
</li><li id="liProducts"> 
    <div class="wrapper"> 
     <uc:Products runat="server" /> 
    </div> 
</li> 
<li> 
    <div class="wrapper"> 
     <div class="preferences"> 
      <uc:Preferences runat="server"/> 
     </div> 

    </div> 
</li> 

+0

基本上我正在寻找加载一个usercontrol点击一个选项卡时按需。没有回传或在更新面板中,以便用户看不到整个页面加载。最好用加载旋转器。 – xoail

+0

你在'UserControl'中有什么?您是否检查权限级别或某种用户组以生成不同的菜单项? – jwiscarson

+0

菜单项对于所有用户都是相同的。他们没有任何检查权限或任何东西。他们是相同的所有用户,除了它的数据(例如:帐户信息0 – xoail

回答

12

您提到的second link应该工作。您不需要在标记中定义任何用户控件。

<ul id="tabs"> 
    <li class="active">Rewards</li> 
    <li id="liCoupons">Coupons</li> 
    <li id="liLibrary">Library</li> 
    <li id="liProducts">Favorite</li> 
    <li id="liPreferences">Preferences</li> 
</ul> 
<div id="results" class="wrapper"></div> 

单击每个标签都会做一个Ajax调用

$.ajax({ 
     type: "POST", 
     url: "Default.aspx/WebMetodToCall", 
     data: data, // I wouldn't prefer passing webmethod name here 
     contentType: "application/json; charset=utf-8", 
     dataType: "json", 
     success: function (msg) { 
      $('#result').html(msg.d); 
     }, 
     failure: function (msg) 
      //error 
     } 
    }); 

到网络的方法。

[WebMethod] 
    public static string Rewards() 
    { 
     return RenderControl("~/controls/rewardsControl.ascx"); 
    } 

[WebMethod] 
    public static string Coupons() 
    { 
     return RenderControl("~/controls/couponsControl.ascx"); 
    }  
... 

每个方法将只呈现请求的控件。同样在您的方法中,您可以根据需要保留或提取视图状态。渲染之后,webmethod应该传回要注入占位符的html字符串。

如果您尝试过这种方式,并且一次成功渲染一个控件但仍然看到缓慢,那么在获取数据时您会遇到一些后端问题。如果你的控件数据量很大,我会建议做一些服务器端缓存。

希望这会有所帮助。

+0

这很好...我们如何做标签点击?喜欢这个?

  • xoail

    +0

    我认为这是一个有点臭(绑定一个AJAX方法到几个WebMethods),但总体而言是这里发布的最佳解决方案(特别是考虑到问题中的特殊环境)。 – jwiscarson

    +0

    @xoail你可以将使用jquery的click事件绑定到你想要的任何DOM元素。看看http://api.jquery.com/click/ – zero7

    6

    请问您的用户控件靠后背部和视图状态的有工作?使用AJAX获取用户控件HTML将显示在选项卡中相对容易,但是在该控件上回发后会将整个数据发送到实际页面(可能没有加载用户控件)。因此,基本轮廓将为

    1. 使用隐藏变量或视图状态跟踪活动选项卡。
    2. 在早期页面循环中基于活动选项卡加载用户控件。最好的选择是初始阶段(不是视图状态在这里不可用,所以你必须将活动标签存储在隐藏变量中并通过Request.Forms集合来访问它)。
    3. 为每个用户控件提供一个ID,它应该不同于制表符。 ID对于加载视图状态非常重要。
    4. 如果在制表切换时出现视图状态错误,那么您需要首先加载用户控件,然后在之后的页面阶段(比如加载/预渲染)加载用户控件,卸载它并加载用于活动选项卡的新用户控件。
    5. 您可以使用每个选项卡窗格中的占位符或面板控件将用户控件加载到正确的位置。
    6. 不用说,关于jquery选项卡的更改,您需要使用后退脚本提交表单。在每次回传之后,您需要有一个脚本来重新初始化选项卡并选择活动选项卡。
    7. 为了更好的用户体验,将整个事物放入UpdatePanel。
    +0

    我不认为我需要查看他们的工作状态。你有任何示例代码或指向我的某个地方? – xoail

    5

    也许使用指向下面定义的服务的锚点。例如,

    <li><a href="...webservices/ControlServce.svc/Content?cType=Rewards" class="wrapper active"></a></li> 
    
    /// <summary> 
    /// Service used by ajax for loading social media content 
    /// </summary> 
    [ServiceContract(Namespace = "")] 
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
    public class ControlService 
    { 
        /// <summary> 
        /// Streams html content 
        /// </summary> 
        /// <param name="type">type of control</param> 
        /// <returns>html stream of content</returns> 
        [OperationContract] 
        [WebGet(UriTemplate = "Content?cType={cType}")] 
        public Stream GetContent(string cType) 
        { 
         var tw = new StringWriter(); 
         var writer = new Html32TextWriter(tw); 
    
         var page = new Page(); 
         var control = page.LoadControl(cType); 
    
         control.RenderControl(writer); 
    
         writer.Close(); 
    
         var stream = new MemoryStream(Encoding.UTF8.GetBytes(tw.ToString())); 
    
         WebOperationContext.Current.OutgoingResponse.ContentType = "text/html"; 
         WebOperationContext.Current.OutgoingResponse.Headers.Add("Cache-Control", "no-cache"); 
         return stream; 
        } 
    } 
    
    +0

    你能展示一些示例代码吗? JS和代码通过ashx处理程序吐出html? – xoail

    3

    你应该去使用jQuery和webmethod的第二个链接。这样,您将实际上按需填充标签,而不会让页面变得沉重。

    5

    您需要进行Ajax调用才能完成此操作。 现在您可以选择调用AJAX:

    1 - 通过SOAP Web服务调用(每个Web方法都需要ASP AjaxScriptManager引用)。

    2-通过WCF服务作为上一个答案进行调用。

    3 - 通过休息服务呼叫。

    4-通过Jquery ajax方法调用,但请求必须转到外部页面,如“Actions.aspx”,所以当你调用你的方法时,一个HTTPRequest将被制作成Actions页面,然后它将在其响应中返回数据。 $.Ajax(url,data,action,successMethod); // this is the fastest way I tried them all.

    这里是你应该做的事: 1上的变化选项卡时使用适当的Ajax调用方法从上面的选项调用你的方法。

    2-从成功方法中使用返回的数据,但最好使用eval(data)作为DataTime对象。

    这里是一些举例说明如何使这个电话:

    var helper = { 
    callAjax: function(sentData, successFun) { 
         jQuery.ajax({ 
          url: "/Actions.aspx", 
          type: "Get", 
          data: sentData, 
          cache: true, 
          dataType: "json", 
          success: successFun 
         }); 
        } 
    }; 
    
    helper.callAjax('request=getCities&countryID=' + countryID, function (args) { 
        var result = eval(args); // this object will contain the returned data 
    var htmlData = ''; 
        for (var i=0;i<result.length;i++){ 
        // write your HTML code by jQuery like this 
        htmlData += '<div>' + result[i].title + '</div>'; 
    } 
    $('#tab3').html(htmlData); 
    }); 
    

    现在在Actions.ASPX代码使用以下命令:

    protected void Page_Load(object sender, EventArgs e) 
        { 
         object _return = new 
         { 
          error = "", 
          status = true 
         }; 
         JavaScriptSerializer _serializer = new JavaScriptSerializer(); 
         if (!Page.IsPostBack) 
         { 
          string str = Request.QueryString["request"].ToString(); 
          switch (str.ToLower()) 
          { 
    case "getcities": 
            int countryID = Convert.ToInt32(Request.QueryString["countryID"].ToString()); 
            _return = JQueryJson.Core.City.getAllCitiesByCountry(countryID).Select(_city => new 
            { 
             id = _city.ID, 
             title = _city.Name 
            }); 
            _serializer = new JavaScriptSerializer(); 
            Response.ClearContent(); 
            Response.ClearHeaders(); 
            Response.ContentType = "text/json"; 
            Response.Write(_serializer.Serialize(_return)); 
            break; 
    } 
    // etc........ 
    } 
    
    +0

    谢谢......不幸的是,在你的回答中,我看到你正在返回json而不是usercontrol它自己。使用$ .ajax,我可以使用.ashx处理程序并返回usercontrol标记吗? – xoail

    3

    在我看来,最快的解决您的问题(但不一定是最好的长期)是将所有的UserControl都包装在.aspx页面中。在这种情况下,您只需将父标记UserControl移动到新的.aspx页面,然后通过AJAX调用它。

    假设你叫这个页面类似Menu.aspx,并进一步假设你并不需要传递到这个网页的任何数据(即,它可以跟踪所有它自己的数据的内部),您的jQuery AJAX调用看起来是这样的:

    function GetMenu ($placeholder) { 
        $.ajax({ type: "POST", contentType: "application/json; charset=utf-8", dataType: "json", 
         url: "Menu.aspx", 
         done: function (result) { 
          $placeholder.html(result.d); 
         }, 
         fail: function() { 
          $placeholder.html("Error loading menu."); 
         } 
        }); 
    } 
    

    一些注意事项:

    1. donefail将取代success和jQuery的1.8 error,所以任何jQuer您使用的AJAX应计划进行此转换。
    2. 我把它包装在一个函数中很大程度上是因为我更喜欢将AJAX调用放在JS类和函数中,然后引用这些对象。有了一个菜单,你不可能有几个不同的页面通过AJAX加载相同的数据(因为这将在某种母版页上,我猜),但总是习惯于这样做的东西。
    3. 根据您对紧耦合HTML/JavaScript的感受,可以使用回调函数替换上面的$placeholder。调用,从你的页面,你的菜单所在看起来是这样的:

      $(document).ready(function() { 
          GetMenu(MenuCallback); 
      }); 
      
      function MenuCallback(menuHtml) { 
          $("#menu").html(menuHtml); // I'm assuming the ID of your ul/span/div tag here. 
      } 
      
    4. 有些人(包括我自己)使用$前缀的JavaScript和jQuery来区分变量。所以在这里,$placeholder是一个jQuery变量。

    5. 您可能可以将此$.ajax呼叫重新编写为type: "GET",这样会更有效一些,但我不确定UserControl是否会在这方面造成问题。通常,如果我通过AJAX加载整个.aspx页面,我使用GET而不是POST。你不需要做太多改变就可以尝试:只需将type属性和result.d更改为result即可。
    +0

    @downvoter,我的回答有什么问题? – jwiscarson

    3

    我认为最好的解决方案是实现客户端回调

    http://msdn.microsoft.com/en-us/library/ms178210.aspx

    当用户点击一些选项卡上,onclick事件调用JS与标签作为参数的名称func,比标签调用服务器具有相同参数的代码。

    比在代码中加载控件要取决于哪个选项卡单击。 现在,您需要将控件呈现为html并将tham发送回js函数。 现在你在js函数中有了控件,找到你要插入代码的地方插入它。

    应在理论工作,它是不复杂的:))

    0

    的asnwer(不是我)这个问题可能对你有用:

    Asynchronous loading of user controls in a page

    它指出,有这是需要用户控件上的表单回传的问题,但是应该可以使用ajax post创建独立的表单。你必须考虑在页面上发布表单时会发生什么,但不应该是无法克服的。不应该有任何理由,你不能让它成为你提到的ashx处理程序。