jQuery Mobile: разрывы при перезагрузке/глубоких ссылках/закладках страниц, добавленных в DOM через AJAX

Я создаю мобильный сайт с помощью jQuery Mobile, и один из моих тестировщиков указал на проблему при повторной загрузке, глубоких ссылках или добавлении закладок на любые страницы, которые я загрузил в DOM, используя стандартную функцию загрузки страниц, встроенную в jQuery. Мобильный. Я просматривал документацию, сообщения на форуме, списки ошибок github и т. д. и т. д. в поисках решения, и я не понимаю, что я могу делать неправильно. Я собрал чрезвычайно простой двухстраничный пример, демонстрирующий то, что я вижу.

Во-первых, у меня есть страница index.html в корневой папке моего примера сайта (то есть /index.html), которая выглядит так:

<!DOCTYPE html>
<html>
<head>
   <title>Home Page</title>
   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
   <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
   <script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.js"></script>
</head>
<body>
<!-- main page -->
<div data-role="page" data-theme="b" id="main">
   <div data-role="header" data-theme="b">
      <h1>Home Page</h1>
   </div><!-- /header -->
   <div data-role="content">
      <ul data-role="listview" data-inset="true">
         <li><a href="news/">News</a></li>
      </ul>
   </div><!-- /content -->
</div><!-- /main page -->
</body>
</html>

У меня есть вторая страница в папке под названием «новости» (т.е. /news/index.html), которая выглядит так:

<div data-role="page" data-theme="b" data-add-back-btn="true" id="news">
   <div data-role="header" data-theme="b">
      <h1>News</h1>
   </div><!-- /header -->
   <div data-role="content">
      TODO: page content goes here
   </div><!-- /content -->
</div><!-- /#news page -->

Итак, это прекрасно работает. «Домашняя страница» загружается нормально. Поле адреса браузера показывает http://m.example.com/.

Я могу щелкнуть ссылку «Новости», чтобы загрузить эту страницу в DOM. Поле адреса браузера теперь показывает http://m.example.com/news/. Вот в чем моя проблема. Если вы нажмете кнопку перезагрузки браузера, страница /news/index.html будет перезагружена, но полностью отсутствует основной контекст домашней страницы, поэтому нет jQuery, css или правильной структуры HTML-документа. Я ожидаю, что это будет иметь место, учитывая URL-адрес и его содержимое документа. Но мне нужны ссылки на подстраницы, чтобы они работали, когда я получаю глубокие ссылки за пределами моего мобильного сайта.

Если вы ссылаетесь на подстраницу с помощью http://m.example.com/#news/, это работает, при этом подстраница загружается правильно, а поле адреса браузера автоматически перезаписывается в http://m.example.com/news/. Проблема в том, что люди должны знать, что им нужно вручную редактировать URL-адрес всякий раз, когда они добавляют в закладки, твитят, отправляют по электронной почте и т. д. URL-адрес страницы.

Есть ли способ автоматически вернуть браузер на домашнюю страницу, а затем вызвать загрузку подстраницы, прозрачной для пользователя, чтобы DOM был воссоздан правильно? Что мне не хватает?


person Brandon    schedule 02.02.2012    source источник


Ответы (4)


Хорошо, основываясь на предложении Кейна, я изменил свой пример кода как таковой, и теперь он работает так, как я хотел.

Страница index.html в корневой папке моего примера сайта (то есть /index.html) теперь выглядит так:

<!DOCTYPE html>
<html>
<head>
   <title>Home Page</title>
   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
   <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
   <script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.js"></script>
   <script type="text/javascript">
if( window.firstload === undefined ) {
    window.firstload = true;
}
   </script>
</head>
<body>
<!-- main page -->
<div data-role="page" data-theme="b" id="main">
   <div data-role="header" data-theme="b">
      <h1>Home Page</h1>
   </div><!-- /header -->
   <div data-role="content">
      <ul data-role="listview" data-inset="true">
         <li><a href="news/">News</a></li>
      </ul>
   </div><!-- /content -->
</div><!-- /main page -->
</body>
</html>

И моя вторая страница в папке под названием «новости» (то есть /news/index.html) теперь выглядит так:

<script type="text/javascript">
if(window.firstload === undefined) {
    for(var i=0, c=0; i < window.location.href.length; i++){
      if(window.location.href.charAt(i) == '/') {
        c++;
        if(c==3) window.location = window.location.href.substr(0,i) 
                                   + '/#'
                                   + window.location.href.substr(i);
      }
    }
}
</script>
<div data-role="page" data-theme="b" data-add-back-btn="false" id="news">
   <div data-role="header" data-theme="b">
      <a href="#main" data-icon="arrow-l" data-iconpos="notext" data-direction="reverse"></a>
      <h1>News</h1>
      <a href="#main" data-icon="home" data-role="button" data-iconpos="notext" data-transition="fade">Home</a>
   </div><!-- /header -->
   <div data-role="content">
      TODO: page content goes here
   </div><!-- /content -->
</div><!-- /#news page -->

Нажатие на перезагрузку или глубокую ссылку/закладку на подстранице теперь перенаправляет посетителя на главную страницу, а затем правильно загружает подстраницу. На подстранице генерируется редирект на http://m.example.com/#/news/.

Надеюсь, эта информация сэкономит кому-то еще несколько часов ударов головой о клавиатуру.

person Brandon    schedule 02.02.2012

Большое спасибо за это решение. Это выдавало мне некоторые ошибки, поэтому я немного упростил его, и теперь он работает для меня:

/**
 * fixes the problem where a subpage in jquerymobile will lose its back button after a refresh. Instead a refresh takes you back to the top page
 * http://stackoverflow.com/questions/9106298/jquery-mobile-breaks-when-reloading-deep-linking-bookmarking-pages-added-to
 */
if(window.firstload === undefined && /#.+$/.test(window.location.href)) {
    window.location = window.location.href.replace(/#.+$/, '');
}

Надеюсь, что это поможет другим, которые испытывают эту проблему.

С наилучшими пожеланиями

Уилл Феррер

person Will Ferrer    schedule 06.12.2012

самый простой способ - перенаправить на главную страницу: Пример subapge: login.htm

<script type="text/javascript">
    window.location="index.htm";
</script>

<div data-role="page" id='login'>
    Ur sub page
</div><!-- /page -->

Код js будет запущен только при перезагрузке страницы, потому что через ajax вставляется только код с data-role="page".

person Sebastian Viereck    schedule 29.12.2012

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

По сути, я просто добавляю сообщение или получаю переменную с именем «partial» в свои запросы ajax, и это решает, включать ли шаблон.

Если вы не хотите выполнять какую-либо работу на стороне сервера (что является идеальным способом сделать это, IMO), то единственный другой способ, который я могу придумать, это добавить что-то вроде этого на каждую страницу:

if( window.firstload === undefined )
{
    // Add script tags and stylesheets to the page and potentially load
    // your site template into the DOM

    window.firstload = true;
}

Когда первая страница загрузится, переменная window.firstload будет неопределенной, поэтому вы можете добавить все теги сценария и таблицы стилей на свою страницу. Затем при последующих загрузках страниц через ajax для window.firstload будет установлено значение true, поэтому это больше не повторится.

person Kane Wallmann    schedule 02.02.2012
comment
Спасибо Кейн! Это было большим подспорьем. - person Brandon; 03.02.2012