在 jquery 选项卡下按需加载用户控件

发布于 2024-12-16 14:12:00 字数 1483 浏览 2 评论 0原文

我在用户控件上有几个 jquery 选项卡,每个选项卡下加载一个单独的用户控件。每个用户控件都是唯一的。目前一切正常,但整体页面响应太慢。为了提高性能,我尝试根据需要(即单击选项卡)在这些选项卡下加载一些用户控件。可能没有回发... ajaxish。 有人可以指导我吗? 我尝试遵循教程和这个 也有一个但没有取得任何成功。我已附上父用户控件的代码。

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

I have few jquery tabs on a usercontrol that loads a separate user control under each. 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.
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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

隔纱相望 2024-12-23 14:12:00
<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
       }
   });

每次单击选项卡都会对 Web 方法

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

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

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

如果您尝试过此操作并成功一次渲染一个控件,但仍然看到速度缓慢,那么您在获取数据时会遇到一些后端问题。如果您的控件数据量很大,我建议您进行一些服务器端缓存。

希望这有帮助。

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({
       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.

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.

笑着哭最痛 2024-12-23 14:12:00

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

  1. 使用隐藏变量或视图状态跟踪活动选项卡。
  2. 在早期页面周期中根据活动选项卡加载用户控件。最好的选择是 init 阶段(并不是说视图状态在这里不可用,因此您必须将活动选项卡存储在隐藏变量中并通过 Request.Forms 集合访问它)。
  3. 为每个用户控件提供一个 ID,并且每个选项卡的 ID 应该不同。 ID 对于加载视图状态非常重要。
  4. 如果在选项卡切换时出现损坏的视图状态错误,则需要首先加载前一个选项卡的用户控件,然后在稍后的页面阶段(例如加载/预呈现),卸载它并加载活动选项卡的新用户控件。
  5. 您可以在每个选项卡窗格中使用占位符或面板控件将用户控件加载到正确的位置。
  6. 不用说,在更改 jquery 选项卡时,您需要使用回发脚本提交表单。每次回发后,您需要一个脚本来重新初始化选项卡并选择活动选项卡。
  7. 为了获得更好的用户体验,请将整个内容放入 UpdatePanel 中。

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). 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).
  3. Give each user control a ID and it should be different from tab to tab. ID is very important for loading the view-state.
  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. 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.
み青杉依旧 2024-12-23 14:12:00

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

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

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;
    }
}
顾冷 2024-12-23 14:12:00

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

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

2- 通过 WCF 服务调用,如之前的答案。

3 - 通过休息服务呼叫。

4-通过 Jquery ajax 方法调用,但请求必须转到外部页面,如“Actions.aspx”,因此当您调用方法时,HTTPRequest 将被放入 Actions 页面,然后它将在其响应中包含返回的数据。 $.Ajax(url,数据,操作,successMethod); // 这是我尝试过的最快的方法。

这是你应该做的:
1- 在更改选项卡事件上,使用上述选项中适当的 Ajax 调用方法来调用您的方法。

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

下面是一些示例,解释了如何进行此调用:

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

You will need to make an Ajax call in order to make this.
now you have options to call AJAX:

1 - Call via SOAP web service (ASP AjaxScriptManager referencing will be needed for every web method).

2- Call via WCF Service as the previous answer.

3 - Call via Rest service.

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

2- from the success method use the returned data but it's better for you to use eval(data) for the DataTime objects.

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:

 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........
}
浮光之海 2024-12-23 14:12:00

如果你用 jquery 稍微调整一下,这应该可以工作:
http://blogs.msdn.com/b/sburke/archive/2007/06/13/how-to-make-tab-control-panels-load-on-demand.aspx

或者您只使用 asp.net 选项卡。

If you adjust it a little with jquery, this should work:
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.

呆° 2024-12-23 14:12:00

您应该使用 jquery 和 webmethod 访问第二个链接。这样,您实际上可以根据需要填充选项卡,而不会增加页面的负担。

You should go for the second link using jquery and webmethod. That way you will actually populate the tabs on demand without making you page heavy.

她说她爱他 2024-12-23 14:12:00

在我看来,解决问题的最快解决方案(但不一定是最好的长期解决方案)是将所有 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 将取代 jQuery 中的 successerror 1.8,所以任何 jQuery您使用的 AJAX 应该为这种转变做好计划。
  2. 我将其包装在一个函数中主要是因为我更喜欢将 AJAX 调用放入 JS 类和函数中,然后引用这些对象。使用菜单,您不太可能有多个不同的页面通过 AJAX 加载相同的数据(我猜这将位于某种母版页上),但是让自己养成执行这些操作的习惯总是好的事物。
  3. 根据您对紧密耦合的 HTML/JavaScript 的感受,您可以将上面的 $placeholder 替换为回调函数。从菜单所在的页面调用它看起来像:

    $(文档).ready(function () {
        获取菜单(菜单回调);
    });
    
    函数菜单回调(menuHtml){
        $("#menu").html(menuHtml); // 我在这里假设您的 ul/span/div 标签的 ID。
    }
    
  4. 有些人(包括我自己)使用 $ 前缀来区分 JavaScript 和 jQuery 变量。所以这里,$placeholder 是一个 jQuery 变量。

  5. 您也许可以将这个 $.ajax 调用重写为 type: "GET",这会更高效,但我不确定如果 UserControl 会导致这方面的问题。通常,如果我通过 AJAX 加载整个 .aspx 页面,我会使用 GET 而不是 POST。您无需进行太多更改即可尝试:只需切换 type 属性并将 result.d 更改为 result 即可。

In my opinion, the fastest solution to your problem (but not necessarily the best long-term) is to wrap all your UserControls in a .aspx page. In this situation, you'd just have to move your parent UserControl markup to a new .aspx page, and call it via 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:

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.
  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. 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.
  3. Depending on your feelings about tightly-coupled HTML/JavaScript, you could replace $placeholder above with a callback function. 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. So here, $placeholder is a jQuery variable.

  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 UserControls would cause problems in that regard. Normally, if I'm loading an entire .aspx page via AJAX, I use GET instead of POST. You don't have to change much to try it out: just switch out the type property and change result.d to result.
南…巷孤猫 2024-12-23 14:12:00

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

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

当用户单击某个选项卡时,onclick 事件以选项卡名称作为参数调用 js func,而不是该选项卡以相同的参数调用服务器代码。

比在代码中,您根据单击的选项卡加载所需的控件。
现在您需要将控件渲染为 html 并将其发送回 js 函数。
现在你已经有了js函数中的控件,找到你想要插入代码的位置并插入它。

理论上应该可行,而且并不复杂:))

I think the best solution is to implement client call back

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.

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.
Now you have controls in js function, find where you want to insert code an insert it.

that should work in theory and it is not to complicated :))

停顿的约定 2024-12-23 14:12:00

这个问题的答案(不是我的)可能对您有用:

异步在页面中加载用户控件

它指出,需要用户控件上的表单来回发存在问题,但是使用 ajax post 拥有独立的表单应该没问题。您必须考虑在页面上发布表单时会发生什么,但这不应该是不可克服的。不应该成为您不能将其设置为您提到的 ashx 处理程序的任何原因。

an asnwer (not mine) to this question is probably useful to you:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文