简体   繁体   English

在jquery选项卡下按需加载usercontrols

[英]Loading usercontrols on demand under jquery tabs

I have few jquery tabs on a usercontrol that loads a separate user control under each. 我在usercontrol上有几个jquery选项卡,在每个选项卡下加载一个单独的用户控件。 Each user control is unique. 每个用户控件都是唯一的。 It all works fine right now but the overall page response is too slow. 一切正常,但整体页面响应太慢。 In order to improve performance I am trying to load few user controls under these tabs on demand (that is on click of tab). 为了提高性能,我尝试按需在这些选项卡下加载少量用户控件(即单击选项卡)。 Possibly without post back... ajaxish. 可能没有回帖...... ajaxish。 Can anyone guide me? 谁能指导我? I tried to follow this tutorial and this one too but did not have any success. 我试图按照教程和一个太多,但没有取得任何结果。 I have attached the code for parent usercontrol. 我已附加父usercontrol的代码。

<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>

The second link you mentioned should work. 你提到的第二个链接应该有效。 You don't need to define any user controls in your markup. 您无需在标记中定义任何用户控件。

<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>

Each tab click will do an ajax call 每个标签点击都会进行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
       }
   });

to the web methods. 到网络方法。

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

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

Each method will render only the requested control. 每种方法都只渲染请求的控件。 Also in your method you can keep or extract the viewstate depending on your needs. 同样在您的方法中,您可以根据需要保留或提取视图状态。 After rendering, the webmethod should pass back the html string to be injected into the placeholders. 渲染后,webmethod应该传回html字符串以注入占位符。

If you tried this and were successful rendering one control at a time but still seeing slowness then you have some back end issues while getting the data. 如果您尝试了这个并且一次成功渲染一个控件但仍然看到缓慢,那么在获取数据时会遇到一些后端问题。 If your controls are data heavy I would recommend doing some server side caching. 如果您的控件数据量很大,我建议您进行一些服务器端缓存。

Hope this helps. 希望这可以帮助。

Does your user controls rely on post-backs and view-state for there working? 您的用户控件是否依赖于后备和视图状态才能正常工作? It will be relative easy to fetch the user control HTML to be displayed in the tab using AJAX but then post-back on that control will send the entire data to the actual page (that may not have the user control loaded). 使用AJAX获取要在选项卡中显示的用户控件HTML相对容易,但是然后在该控件上回发将整个数据发送到实际页面(可能没有加载用户控件)。 So the basic outline would be 所以基本的纲要是

  1. Track the active tab using hidden variable or view-state. 使用隐藏变量或视图状态跟踪活动选项卡。
  2. Load the user control based on active tab in the early page cycle. 在早期页面循环中基于活动选项卡加载用户控件。 The best bet would be init stage (not that view-state won't be available here, so you have to store active tab in hidden variable and access it via Request.Forms collection). 最好的选择是初始阶段(不是视图状态在这里不可用,所以你必须在隐藏变量中存储活动选项卡并通过Request.Forms集合访问它)。
  3. Give each user control a ID and it should be different from tab to tab. 为每个用户控件提供一个ID,它应该与tab到tab不同。 ID is very important for loading the view-state. ID对于加载视图状态非常重要。
  4. If you get corrupted view-state errors at tab switching then you need to first load the user control for the previous tab and then at later page stage (say load/prerender), unload it and load new user control for active tab. 如果在切换选项卡时出现视图状态错误,则需要首先加载前一个选项卡的用户控件,然后再加载到页面的后一页(比如加载/预渲染),卸载它并为活动选项卡加载新的用户控件。
  5. You can use a placeholder or panel control within each tab pane to load the user control in the correct location. 您可以在每个选项卡窗格中使用占位符或面板控件将用户控件加载到正确的位置。
  6. Needless to say, on change of jquery tab, you need to submit your form using post-back script. 不用说,在更改jquery选项卡时,您需要使用post-back脚本提交表单。 After every post-back, you need to have a script to re-initialize tabs and selecting active tab. 每次回发后,您都需要有一个脚本来重新初始化选项卡并选择活动选项卡。
  7. For better user experience, put entire thing into an UpdatePanel. 为了获得更好的用户体验,请将整个内容放入UpdatePanel中。

perhaps use an anchor that points to the service defined below. 也许使用指向下面定义的服务的锚点。 For instance, 例如,

<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;
    }
}

You will need to make an Ajax call in order to make this. 您需要进行Ajax调用才能实现此目的。 now you have options to call AJAX: 现在您可以选择调用AJAX:

1 - Call via SOAP web service (ASP AjaxScriptManager referencing will be needed for every web method). 1 - 通过SOAP Web服务调用(每个Web方法都需要ASP AjaxScriptManager引用)。

2- Call via WCF Service as the previous answer. 2-通过WCF服务呼叫作为上一个答案。

3 - Call via Rest service. 3 - 通过休息服务致电。

4- Call via Jquery ajax method but the request must going to external page like "Actions.aspx" so when you call your method an HTTPRequest will be made into Actions page then it will have the returned data within its response. 4-通过Jquery ajax方法调用,但请求必须转到外部页面,如“Actions.aspx”,因此当您调用方法时,HTTPRequest将进入Actions页面,然后它将在其响应中返回返回的数据。 $.Ajax(url,data,action,successMethod); // this is the fastest way I tried them all.

Here is what you should to do: 1- on the change tab event call your method by using the appropriate Ajax calling method from the above options. 以下是您应该做的事情:1-在更改选项卡上,通过使用上述选项中的相应Ajax调用方法调用您的方法。

2- from the success method use the returned data but it's better for you to use eval(data) for the DataTime objects. 成功方法中的2-使用返回的数据,但最好使用eval(数据)作为DataTime对象。

here is some example explains how to make this call: 这里有一些例子解释了如何进行此调用:

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);
});

now at the Actions.ASPX code use the following: 现在在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........
}

If you adjust it a little with jquery, this should work: 如果你用jquery稍微调整它,这应该工作:
http://blogs.msdn.com/b/sburke/archive/2007/06/13/how-to-make-tab-control-panels-load-on-demand.aspx http://blogs.msdn.com/b/sburke/archive/2007/06/13/how-to-make-tab-control-panels-load-on-demand.aspx

Or you just use the asp.net tabs. 或者你只是使用asp.net选项卡。

You should go for the second link using jquery and webmethod. 你应该使用jquery和webmethod去第二个链接。 That way you will actually populate the tabs on demand without making you page heavy. 这样,您实际上可以根据需要填充选项卡,而不会让您的页面变得很重。

In my opinion, the fastest solution to your problem (but not necessarily the best long-term) is to wrap all your UserControl s in a .aspx page. 在我看来,解决问题的最快方法(但不一定是最好的长期解决方案)是将所有UserControl包装在.aspx页面中。 In this situation, you'd just have to move your parent UserControl markup to a new .aspx page, and call it via AJAX. 在这种情况下,您只需将父UserControl标记移动到新的.aspx页面,然后通过AJAX调用它。

Assuming that you called this page something like Menu.aspx , and further assuming that you don't need any data passed into this page (that is, it can track all of its own data internally), your jQuery AJAX call would look something like this: 假设您将此页面称为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.");
        }
    });
}

Some notes: 一些说明:

  1. done and fail will replace success and error in jQuery 1.8, so any jQuery AJAX you use should plan for this transition. donefail将取代jQuery 1.8中的successerror ,因此您使用的任何jQuery AJAX都应该计划此转换。
  2. I wrapped this in a function largely because I prefer to put AJAX calls inside JS classes and functions, and then reference those objects. 我把它包装在一个函数中很大程度上是因为我更喜欢将AJAX调用放在JS类和函数中,然后引用这些对象。 With a menu, it's unlikely you'd have several different pages loading the same data via AJAX (since this will be on some sort of master page, I'm guessing), but it's always good to get yourself in the habit of doing these things. 有了一个菜单,你不可能有几个不同的页面通过AJAX加载相同的数据(因为这将在某种母版页上,我猜),但是让自己养成做这些的习惯总是好的的东西。
  3. Depending on your feelings about tightly-coupled HTML/JavaScript, you could replace $placeholder above with a callback function. 根据您对紧密耦合的HTML / JavaScript的感受,您可以使用回调函数替换上面的$placeholder Calling that from your the page where your menu resides would look something like: 从您的菜单所在的页面调用它将类似于:

     $(document).ready(function () { GetMenu(MenuCallback); }); function MenuCallback(menuHtml) { $("#menu").html(menuHtml); // I'm assuming the ID of your ul/span/div tag here. } 
  4. Some people (myself included) use the $ prefix to differentiate between JavaScript and jQuery variables. 有些人(包括我自己)使用$前缀来区分JavaScript和jQuery变量。 So here, $placeholder is a jQuery variable. 所以这里, $placeholder是一个jQuery变量。

  5. You might be able to re-write this $.ajax call as a type: "GET" , which would be a little bit more efficient, but I'm not sure if the UserControl s would cause problems in that regard. 您可以将这个$.ajax调用重新编写为type: "GET" ,这会更高效,但我不确定UserControl是否会在这方面引起问题。 Normally, if I'm loading an entire .aspx page via AJAX, I use GET instead of POST . 通常,如果我通过AJAX加载整个.aspx页面,我使用GET而不是POST You don't have to change much to try it out: just switch out the type property and change result.d to result . 您不需要做太多改动就可以尝试:只需切换type属性并将result.d更改为result

I think the best solution is to implement client call back 我认为最好的解决方案是实现客户端回调

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

When user clicks on some tab,onclick event calls js func with name of tab as parameter, than that tab calls server code with same parameter. 当用户单击某个选项卡时,onclick事件会调用名称为tab作为参数的js func,而该选项卡会调用具有相同参数的服务器代码。

Than in code you load controls you want depending which tab is clicked. 在代码中,您可以根据单击的选项卡加载所需的控件。 Now you need to render controls into html and send tham back to js function. 现在你需要将控件渲染为html并将tham发送回js函数。 Now you have controls in js function, find where you want to insert code an insert it. 现在你有了js函数中的控件,找到你要插入代码的位置。

that should work in theory and it is not to complicated :)) 这应该在理论上工作,它不复杂:))

an asnwer (not mine) to this question is probably useful to you: asnwer(不是我的)对这个问题可能对你有用:

Asynchronous loading of user controls in a page 在页面中异步加载用户控件

it states that there are problems with this with needing a form on the user control to post back, but that should be ok to have independent forms with ajax post. 它表示在使用用户控件上的表单需要回发时存在问题,但是可以使用带有ajax帖子的独立表单。 you'll have to think about what happens when posting the form(s) on the page, but shouldn't be insurmountable. 你必须考虑在页面上发布表单时会发生什么,但不应该是不可克服的。 shouldn't be any reason you couldn't just make it the ashx handler you have mentioned. 不应该是任何理由你不能把它作为你提到的ashx处理程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM