Привязка Ajax-кода jQuery для мобильной страницы ASP.NET MVC3 с использованием события PageInit - PullRequest
1 голос
/ 11 октября 2011

Мы пишем приложение JQueryMobile, используя ASP.NET MVC3 + JqueryMobile RC1. У немногих страниц есть свои собственные методы Ajax, которые мы вызываем с помощью метода кода jQuery ($.getJSON()).

Чтобы вызвать их в вызовах Ajax, мы делаем привязки событий внутри события «pageinit» jquery-mobile, как упомянуто здесь (http://jquerymobile.com/demos/1.0rc1/docs/api/events.html). Но вызов метода, привязанного к pageinit, увеличивается на +1 при каждом посещении страницы. например если я снова зайду на свою страницу с помощью кнопки «Назад» или по любой другой ссылке, зайдите на нее снова, метод pageinit вызывается дважды, а любой код, написанный внутри pageinit, выполняется два раза ... они увеличиваются с каждым посещением страницы.

Какое событие мы должны использовать, чтобы связать события. и он должен вызываться только один раз при загрузке страницы?

Edit: - Нам нужно поведение JQM по умолчанию в AJAX, и мы сохранили для AjaxEnabled значение true.

Образец исходного кода (вы можете воспроизвести эту проблему, создав новое приложение MVC3 и заменив ниже три .cshtml на данный код: -

Мой _Layout.cshtml: -

<!DOCTYPE html>
<html>
<head>  
    <meta name="viewport" content="width=device-width" />
    <meta charset="utf-8" />
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0rc1/jquery.mobile-1.0rc1.min.css" />
    <script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script type="text/javascript">
        $(document).bind("mobileinit", function () {
            $.mobile.ajaxEnabled = true;
        });
    </script>
    <script src="http://code.jquery.com/mobile/1.0rc1/jquery.mobile-1.0rc1.min.js"></script>
    @RenderSection("HeaderScripts", required: false)
</head>
<body>
    <div data-role="page" id="@ViewBag.DivTitle">
        <div data-role="header">
            <h1>
                @ViewBag.Title
            </h1>
             <a href="/Home/About" data-role="Button" data-icon="info"  data-iconpos="notext">About</a>
              <a href="/Home/Index" data-role="Button" data-icon="home"  data-iconpos="notext">Home</a>
        </div>

        <div data-role="content" id="DivContent">
            @RenderBody()
            @RenderSection("BodyScriptsSection", required: false)
        </div>

        <div data-role="footer" data-position="fixed">
            @RenderSection("MobileFooter", required: false)
        </div>
    </div>
</body>
</html>

Пример Index.cshtml

@{
    ViewBag.Title = "Home Page";
    ViewBag.DivTitle = "HomeIndex";
}

@section BodyScriptsSection {
  <script type="text/javascript">
      $("#@ViewBag.DivTitle").live("pageshow", function () {
      alert ("PageShow Called - HomeIndex");
  });

      </script>

Пример AboutUS.cshtml

@{
    ViewBag.Title = "About Us";
    ViewBag.DivTitle = "AboutUS";

}

@section BodyScriptsSection {
  <script type="text/javascript">
      $("#@ViewBag.DivTitle").live("pageshow", function () {
          alert("PageShow Called - AboutUS");
      });

      </script>

Ответы [ 6 ]

2 голосов
/ 13 октября 2011

Почему бы вам не убить своих обработчиков после ухода, что-то вроде этого:

$("#@ViewBag.DivTitle").live("pagehide", function() {
    $("#@ViewBag.DivTitle").die("pageshow");
}
1 голос
/ 14 октября 2011

Два варианта:

1. используйте один () вместо bind () или live ()
Пока страница не удаляется из DOM, это должно помочь. Смотрите здесь .

В нем говорится: «прикрепить обработчик к событию для элемента. Обработчик выполняется не более одного раза для элемента.»

Jquery Mobile также использует его внутри JQM, вероятно, по той же причине. Так что, если вы делаете так:

$('button').one('click', function () { do something });

, который должен стрелять только один раз.

2. Используйте data () для установки флага после возникновения события
Другая идея состоит в том, чтобы использовать data () для прикрепления флага к элементу страницы или, поскольку страницы могут быть удалены из DOM, лучше присоединить его к элементу HTML или BODY. Они останутся ...

Я запускаю прокрутку на страницах (надеюсь, однажды), например:

$('div[data-role="page"]').live('pagebeforeshow.scroll', function(event){
     var $page = $(this);
     if ( $page.data('scrollable', 'Off') ) {
         $page.data('scrollable', 'On');
         scrollMe( $page ); // init
         }
      });       

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

EDIT:

Это также работает для меня, используя attr:

    // on pageinit - set global argument
    $('html').attr('fire-once', 'Off'); 

    $( '#your page' ).live( 'pageshow',function(event){
    if ( $('html').attr('fire-once') == 'Off' ) {
            $('html').attr('fire-once', 'On');
            // your button.bind.behavior here
            }
       });

Таким образом, вы устанавливаете «огонь один раз» для элемента HTML, который всегда будет одинаковым в JQM при загрузке и выходе страниц. Только если вы перейдете на страницу с data-rel = "external", fire-Once будет сброшен.

На указанной вами странице вы прослушиваете pagehow, запускаете функцию, которая сначала переключает один раз на «On», а затем добавляет привязку вашей кнопки.

Поскольку функция fire-once теперь включена, даже при нескольких привязках оператор if не будет выполнен, и вы будете назначать поведение кнопки только один раз.

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

Отправьте мне сообщение, если хотите увидеть живой пример.

Приветствия

Частое

1 голос
/ 13 октября 2011

Используя инфраструктуру jQuery Mobile, если вы поместите <script> внутри элемента <div data-role="page">, он будет запускаться каждый раз, когда отображается страница, и если вы связываете обработчики событий внутри кода, они будут связаны каждый раз, когда страницасчитается, что DOM остается неизменным во время навигации по сайту.

Попробуйте переместить оператор @RenderSection("BodyScriptsSection", required: false) в конец страницы, непосредственно перед закрывающим тегом </body>.Таким образом, сценарий будет включаться при каждом полном обновлении (например, если пользователь нажимает кнопку обновления) и если пользователь делает глубокие ссылки на ваш сайт;однако он не будет запускаться каждый раз, когда страница собирается с помощью навигации JJuery Mobile по AJAX.

Вы также можете решить эту проблему, кэшируя каждую страницу, чтобы ее не нужно было собирать с помощью навигации AJAX при последующих посещениях.на страницу.По умолчанию jQuery Mobile Beta 3 и более поздние версии (в настоящее время RC 1) удаляют страницы из DOM после того, как пользователь от них отказался (однако привязанные обработчики событий не удаляются), эта функция помогает контролировать размер DOM,Для кэширования страницы добавьте data-dom-cache="true" к элементу <div data-role="page">.

0 голосов
/ 13 октября 2011

Ваш пример кода использует «pageshow» вместо «pageinit»«Pageinit» должен работать нормально.

0 голосов
/ 11 октября 2011

Похоже, вам может понадобиться свернуть код в IsPostBack чек.Например:

void Page_Init(object sender, EventArgs e) 
{
    if (!IsPostBack)
    {
        RegisterScriptHere();
    }
}

РЕДАКТИРОВАТЬ

При втором чтении вы можете не спрашивать о серверной стороне, если вы пытаетесь сделать это на клиентесторона, проигнорируй мой ответ.

0 голосов
/ 11 октября 2011

Вы можете хранить переменную IsPageInitialized = false для каждой страницы, связывать события только в том случае, если эта переменная имеет значение false, и устанавливать ее в значение true при назначении обработчиков событий.

...