Загрузка пользовательских элементов управления по требованию во вкладках jquery - PullRequest
10 голосов
/ 17 ноября 2011

У меня есть несколько вкладок 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>

Ответы [ 9 ]

12 голосов
/ 29 ноября 2011

вторая ссылка , которую вы упомянули, должна работать.Вам не нужно определять какие-либо пользовательские элементы управления в вашей разметке.

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

Каждый метод будет отображать только запрошенный элемент управления.Также в вашем методе вы можете сохранить или извлечь состояние представления в зависимости от ваших потребностей.После рендеринга веб-метод должен передать обратно строку html, которая будет внедрена в заполнители.

Если вы попытались это сделать и успешно отрисовывали один элемент управления за раз, но все еще видели медлительность, то у вас возникли некоторые проблемы с сервером при полученииданные.Если ваши элементы управления перегружены данными, я бы порекомендовал выполнить кэширование на стороне сервера.

Надеюсь, это поможет.

6 голосов
/ 17 ноября 2011

Ваш пользовательский контроль полагается на post-backs и view-state для их работы?Относительно легко получить HTML-код пользовательского элемента управления, который будет отображаться на вкладке, с помощью AJAX, но затем последующий ответ на этом элементе управления отправит все данные на фактическую страницу (которая может не иметь загруженного пользовательского элемента управления).Таким образом, базовая схема будет

  1. Отслеживать активную вкладку с помощью скрытой переменной или состояния просмотра.
  2. Загрузка пользовательского элемента управления на основе активной вкладки в раннем цикле страниц.Лучше всего было бы начать этап (не то, что состояние просмотра здесь не будет доступно, поэтому вы должны хранить активную вкладку в скрытой переменной и обращаться к ней через коллекцию Request.Forms).
  3. Предоставьте каждому пользователю контрольидентификатор и он должен отличаться от вкладки к вкладке.Идентификатор очень важен для загрузки состояния просмотра.
  4. Если вы получаете поврежденные ошибки состояния просмотра при переключении вкладок, вам нужно сначала загрузить пользовательский элемент управления для предыдущей вкладки, а затем на более позднем этапе страницы (скажем, загрузить/ prerender), выгрузите его и загрузите новый пользовательский элемент управления для активной вкладки.
  5. Вы можете использовать заполнитель или элемент управления панели в каждой панели вкладок, чтобы загрузить пользовательский элемент управления в правильном месте.
  6. Нет необходимости говорить, что при смене вкладки jquery вам необходимо отправить форму, используя скрипт обратной передачи.После каждого постбэка вам необходим скрипт для повторной инициализации вкладок и выбора активной вкладки.
  7. Для лучшего взаимодействия с пользователем поместите все это в UpdatePanel.
5 голосов
/ 29 ноября 2011

Вам нужно будет сделать Ajax-вызов, чтобы сделать это. Теперь у вас есть возможность позвонить в AJAX:

1 - вызов через веб-службу SOAP (для каждого веб-метода потребуется ссылка на ASP AjaxScriptManager).

2- Позвоните через службу WCF в качестве предыдущего ответа.

3 - звонок через службу отдыха.

4- Вызовите через Jjery ajax метод, но запрос должен идти на внешнюю страницу, такую ​​как «Actions.aspx», поэтому, когда вы вызываете ваш метод, HTTPRequest будет сделан на странице Actions, тогда в ответе будут возвращены данные. $.Ajax(url,data,action,successMethod); // this is the fastest way I tried them all.

Вот что вы должны сделать: 1- на событии вкладки изменения вызовите ваш метод, используя соответствующий метод вызова Ajax из указанных выше вариантов.

2 - из метода успеха используйте возвращенные данные, но для объектов 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........
}
5 голосов
/ 28 ноября 2011

возможно использовать привязку, которая указывает на сервис, определенный ниже. Например,

<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;
    }
}
3 голосов
/ 29 ноября 2011

Я думаю, что лучшее решение - реализовать обратный вызов клиента

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

Когда пользователь нажимает на какую-либо вкладку, событие onclick вызывает js func с именем вкладки в качестве параметра, а затем эта вкладка вызывает код сервера с таким же параметром.

Чем в коде вы загружаете нужные элементы управления, в зависимости от того, какая вкладка нажата. Теперь вам нужно отобразить элементы управления в html и отправить их обратно в функцию js. Теперь у вас есть элементы управления в функции js, найдите, куда вы хотите вставить код и вставьте его.

это должно работать в теории, и это не сложно:))

3 голосов
/ 29 ноября 2011

На мой взгляд, самое быстрое решение вашей проблемы (но не обязательно долгосрочного) - это обернуть все ваши 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. done и fail заменит success и error в jQuery 1.8, поэтому любой JQuery 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 s вызовет проблемы в этом отношении.Обычно, если я загружаю всю страницу .aspx через AJAX, я использую GET вместо POST.Вам не нужно много менять, чтобы попробовать это: просто отключите свойство type и измените result.d на result.
3 голосов
/ 29 ноября 2011

Вы должны перейти на вторую ссылку, используя jquery и webmethod. Таким образом, вы фактически будете заполнять вкладки по требованию, не делая вашу страницу тяжелой.

3 голосов
/ 23 ноября 2011

Если вы немного отрегулируете его с помощью jquery, это должно сработать:
http://blogs.msdn.com/b/sburke/archive/2007/06/13/how-to-make-tab-control-panels-load-on-demand.aspx

Или вы просто используете вкладки asp.net.

0 голосов
/ 30 ноября 2011

Ответ (не мой) на этот вопрос, вероятно, полезен для вас:

Асинхронная загрузка пользовательских элементов управления на странице

говорит о наличии проблемэто требует наличия формы в пользовательском элементе управления для отправки сообщений назад, но это нормально, если у вас есть независимые формы с сообщением ajax.вам придется подумать о том, что происходит при размещении форм на странице, но это не должно быть непреодолимым.не должно быть никаких причин, по которым вы не можете просто сделать это обработчиком ashx, о котором вы упоминали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...