jQuery Mobile:重新加载/深层链接/书签通过AJAX添加到DOM的页面时中断

时间:2022-09-19 09:13:37

I'm building out a mobile site using jQuery Mobile and one of my testers pointed out a problem when re-loading, deep linking to, or bookmarking any pages that I've loaded into the DOM using the standard page loading functionality built into jQuery Mobile. I've been reviewing the documentation, forum posts, github bug lists, etc, etc looking for a solution and I'm at my wits end on what I might be doing wrong. I've compiled an extremely basic two page example that demonstrates what I'm seeing.

我正在使用jQuery Mobile构建一个移动网站,我的一个测试人员在使用jQuery内置的标准页面加载功能重新加载,深度链接或加入我加载到DOM中的任何页面时指出了一个问题移动。我一直在审查文档,论坛帖子,github错误列表等等,寻找解决方案,我在我的智慧结束我可能做错了什么。我编写了一个非常基本的两页示例,演示了我所看到的内容。

First off, I've got an index.html page in my example site root folder (i.e. /index.html) that looks like this:

首先,我在我的示例站点根文件夹(即/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>

I've got a second page in a folder called 'news' (i.e. /news/index.html) that looks like this:

我在名为'news'的文件夹(即/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 -->

So, this works great. The "home page" loads fine. The browser address field shows http://m.example.com/.

所以,这很有效。 “主页”加载正常。浏览器地址字段显示http://m.example.com/。

I can click the 'News' link to load that page into the DOM. The browser address field now shows http://m.example.com/news/. This is where my problem lies. If you click the browser reload button, the /news/index.html page gets reloaded but is completely missing the main home page context, so no jQuery, css or proper HTML document structure. I'd expect that to be the case given the URL and its document content. But I need links to sub-pages to work when being deep linked to from outside my mobile site.

我可以点击“新闻”链接将该页面加载到DOM中。浏览器地址字段现在显示http://m.example.com/news/。这就是我的问题所在。如果单击浏览器重新加载按钮,则会重新加载/news/index.html页面,但完全缺少主页面上下文,因此没有jQuery,css或正确的HTML文档结构。鉴于URL及其文档内容,我希望是这种情况。但是,当我从移动网站外部深层链接时,我需要链接到子页面。

If you link to the subpage using http://m.example.com/#news/, this works, with the subpage loading correctly and the browser address field getting automatically rewritten to http://m.example.com/news/. The problem with this is that people would need to know that they need to manually edit the URL whenever they bookmark, tweet, e-mail, etc the page URL.

如果您使用http://m.example.com/#news/链接到子页面,则可以正常加载子页面,并且浏览器地址字段会自动重写为http://m.example.com/news/ 。这样做的问题是人们需要知道他们需要在书签,推文,电子邮件等页面URL时手动编辑URL。

Is there a way to automatically kick the browser back to the home page and then trigger the loading of the subpage, transparent to the user, so that the DOM is re-created correctly? What am I missing?

有没有办法自动将浏览器踢回主页,然后触发加载子页面,对用户透明,以便正确地重新创建DOM?我错过了什么?

4 个解决方案

#1


3  

Okay, based on Kane's suggestion, I've modified my sample code as such and it now seems to work as I wanted.

好的,基于Kane的建议,我已经修改了我的示例代码,它现在看起来像我想要的那样工作。

The index.html page in my example site root folder (i.e. /index.html) now looks like this:

我的示例站点根文件夹(即/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>

And my second page in a folder called 'news' (i.e. /news/index.html) now looks like this:

我在名为'news'的文件夹中的第二页(即/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 -->

Hitting reload, or deep linking/bookmarking, on the subpage now bounces the visitor up to the main page and then loads in the subpage properly. In the subpage, the redirect is generated to http://m.example.com/#/news/.

点击子页面上的重新加载或深层链接/书签,现在可以将访问者反弹到主页面,然后正确地加载到子页面中。在子页面中,重定向生成为http://m.example.com/#/news/。

Hopefully this info will save someone else a few hours of banging their head on the keyboard.

希望这些信息可以节省其他人几个小时的敲击键盘。

#2


1  

Thank you very much for this solution. It was giving me some errors so I simplified it a bit and it seems to be working for me now:

非常感谢您的解决方案。它给了我一些错误,所以我简化了一下,它现在似乎对我有用:

/**
 * 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://*.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(/#.+$/, '');
}

Hope that helps others that are experiencing this issue.

希望能帮助遇到此问题的其他人。

Best regards

最好的祝福

Will Ferrer

威尔费雷尔

#3


1  

the easiest way is to redirect to the main page: Example subapge: login.htm

最简单的方法是重定向到主页面:示例subapge:login.htm

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

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

The js code will only be fired, when the page is reloaded, because only the code with data-role="page" is inserted via ajax.

只有在重新加载页面时才会触发js代码,因为只有通过ajax插入了带有data-role =“page”的代码。

#4


0  

I have a similar situation where I use some server-side processing to determine whether to render the content in my site template for new requests or just the content on its own for requests from ajax.

我有一个类似的情况,我使用一些服务器端处理来确定是否在我的网站模板中为新请求呈现内容,或仅为ajax请求呈现内容。

Basically, I just add a post or get variable called 'partial' to my ajax requests and that decides whether to include the template.

基本上,我只是添加一个帖子或获取名为'partial'的变量到我的ajax请求,并决定是否包含模板。

If you do not want to do any server-side work (which is the ideal way to do it IMO) then the only other way I can think of is to add something like this to every page:

如果你不想做任何服务器端的工作(这是做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;
}

When the first page loads the variable window.firstload will be undefined so you can add all the script tags and stylesheets to your page. Then on subsequent page loads via ajax window.firstload will be set to true so it won't happen again.

当第一个页面加载变量window.firstload时将是未定义的,因此您可以将所有脚本标记和样式表添加到页面中。然后通过ajax window.firstload将后续页面加载设置为true,这样就不会再发生了。

#1


3  

Okay, based on Kane's suggestion, I've modified my sample code as such and it now seems to work as I wanted.

好的,基于Kane的建议,我已经修改了我的示例代码,它现在看起来像我想要的那样工作。

The index.html page in my example site root folder (i.e. /index.html) now looks like this:

我的示例站点根文件夹(即/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>

And my second page in a folder called 'news' (i.e. /news/index.html) now looks like this:

我在名为'news'的文件夹中的第二页(即/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 -->

Hitting reload, or deep linking/bookmarking, on the subpage now bounces the visitor up to the main page and then loads in the subpage properly. In the subpage, the redirect is generated to http://m.example.com/#/news/.

点击子页面上的重新加载或深层链接/书签,现在可以将访问者反弹到主页面,然后正确地加载到子页面中。在子页面中,重定向生成为http://m.example.com/#/news/。

Hopefully this info will save someone else a few hours of banging their head on the keyboard.

希望这些信息可以节省其他人几个小时的敲击键盘。

#2


1  

Thank you very much for this solution. It was giving me some errors so I simplified it a bit and it seems to be working for me now:

非常感谢您的解决方案。它给了我一些错误,所以我简化了一下,它现在似乎对我有用:

/**
 * 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://*.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(/#.+$/, '');
}

Hope that helps others that are experiencing this issue.

希望能帮助遇到此问题的其他人。

Best regards

最好的祝福

Will Ferrer

威尔费雷尔

#3


1  

the easiest way is to redirect to the main page: Example subapge: login.htm

最简单的方法是重定向到主页面:示例subapge:login.htm

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

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

The js code will only be fired, when the page is reloaded, because only the code with data-role="page" is inserted via ajax.

只有在重新加载页面时才会触发js代码,因为只有通过ajax插入了带有data-role =“page”的代码。

#4


0  

I have a similar situation where I use some server-side processing to determine whether to render the content in my site template for new requests or just the content on its own for requests from ajax.

我有一个类似的情况,我使用一些服务器端处理来确定是否在我的网站模板中为新请求呈现内容,或仅为ajax请求呈现内容。

Basically, I just add a post or get variable called 'partial' to my ajax requests and that decides whether to include the template.

基本上,我只是添加一个帖子或获取名为'partial'的变量到我的ajax请求,并决定是否包含模板。

If you do not want to do any server-side work (which is the ideal way to do it IMO) then the only other way I can think of is to add something like this to every page:

如果你不想做任何服务器端的工作(这是做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;
}

When the first page loads the variable window.firstload will be undefined so you can add all the script tags and stylesheets to your page. Then on subsequent page loads via ajax window.firstload will be set to true so it won't happen again.

当第一个页面加载变量window.firstload时将是未定义的,因此您可以将所有脚本标记和样式表添加到页面中。然后通过ajax window.firstload将后续页面加载设置为true,这样就不会再发生了。