如何使用 Backbone.js 在 changePage 后显示 JQuery Mobile 主页面
Posted
技术标签:
【中文标题】如何使用 Backbone.js 在 changePage 后显示 JQuery Mobile 主页面【英文标题】:How to get main JQuery Mobile page to display after changePage using Backbone.js 【发布时间】:2013-12-06 07:54:23 【问题描述】:我正在开发一个同时使用 RequireJS 和 BackboneJS 的 JQuery Mobile 应用程序 (1.4rc1)。该应用程序还没有那么复杂,但是太多了。我已经能够设置路由器并且它正在正确调用路由方法。我的页面,除了主页(位于index.html
),保存在一个名为“/pages”的目录中。
应用程序加载正常并调用家庭路由器功能。稍后我将禁用该行为。
我点击登录链接,它会加载 /pages/login-page.html
并将页面添加到 DOM 并显示它。
问题:
当我点击后退按钮时,将调用 home 的路由器功能,然后调用 $.mobile.changePage("#mainpage")
但不会重新显示主页,也不会显示任何错误。
我已经确定 mainpage
仍在 DOM 中,并且正在调用正确的路由器函数。
为什么即使我调用了changePage,主页也不会重新显示? 日志:
before start mobileRouter.js:5
before home: http://localhost:8080/host/index.html mobileRouter.js:14
after home: http://localhost:8080/host/index.html#mainpage mobileRouter.js:16
after start mobileRouter.js:7
before login: http://localhost:8080/host/index.html#mainpage mobileRouter.js:19
after login: http://localhost:8080/host/index.html mobileRouter.js:21
before home: http://localhost:8080/host/pages/login-page.html mobileRouter.js:14
after home: http://localhost:8080/host/index.html#mainpage mobileRouter.js:16
相关代码:
mobileRouter.js
define(["jquery", "backbone"],
function($, Backbone)
var Router = Backbone.Router.extend(
initialize: function()
console.log("before start");
Backbone.history.start();
console.log("after start");
,
routes:
"": "mainPage",
"loginpage": "loginPage",
,
mainPage: function()
console.log("before home: " + document.baseURI);
$.mobile.changePage("#mainpage");
console.log("after home: " + document.baseURI);
,
loginPage: function()
console.log("before login: " + document.baseURI);
$.mobile.changePage("pages/login-page.html");
console.log("after login: " + document.baseURI);
);
return Router;
);
index.html
<!doctype html>
<html class="no-js ui-mobile-rendering" lang="en">
<head>
<title>The Measure Of It</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="lib/dev/jquery.mobile.structure-1.4.0-rc.1.css">
<link rel="stylesheet" href="lib/dev/jquery.mobile.theme-1.4.0-rc.1.css">
<script src="require.js" data-main="mobile"></script>
</head>
<body>
<div data-role="page" id="mainpage">
<div data-role="header">
<h1>Main Page</h1>
</div><!-- /header -->
<div data-role="content">
<p><a href="#loginpage">Login</a></p>
</div><!-- /content -->
<div data-role="footer">
<h4>Page Footer</h4>
</div><!-- /footer -->
</div>
</body>
</html>
/pages/login-page.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>page demo</title>
</head>
<body>
<div data-role="page" id="loginpage">
<div data-role="header">
<h1>Login</h1>
</div>
<div data-role="content">
<h2>email</h2>
<h2>password</h2>
</div>
<div data-role="footer">
<h1>Login Footer</h1>
</div>
</div>
</body>
</html>
mobile.js
require.config(
paths:
"jquery": "lib/dev/jquery-1.10.2",
"jquerymobile": "lib/dev/jquery.mobile-1.4.0-rc.1",
"underscore": "lib/dev/lodash",
"backbone": "lib/dev/backbone",
"routers": "app/routers",
,
shim:
"backbone":
"deps": ["underscore", "jquery"],
"exports": "Backbone"
);
require(["jquery", "backbone", "routers/mobileRouter"], function($, Backbone, Mobile)
$(document).on("mobileinit",
function()
$.mobile.linkBindingEnabled = false;
$.mobile.hashListeningEnabled = false;
);
require(["jquerymobile"], function()
this.router = new Mobile();
);
);
【问题讨论】:
$.mobile.changePage()
在 jqm 1.4 中已弃用并替换为$.mobile.pageContainer.pagecontainer ("change", "#page_id");
,试试看。
相同的行为,但很高兴知道。
在更改页面中尝试 index.html
而不是 #mainpage
。
我希望不要陷入这个特殊问题,但是......它失败了,但它确实在 index.html 上执行了 GET。这有两个问题:它不需要执行 GET,因为主页面在 DOM 中,并且由于我不想处理的错误(但)它尝试从同一个页面加载 index.html目录,因为它从中加载登录页面,因此找不到它。
我不是骨干专家,但请帮我一个忙,当你点击返回按钮console.log($.mobile.pageContainer.pagecontainer("getActivePage").prev("[data-role=page]").length);
时添加这一行如果它返回0,那么登录页面就没有前一页了。也试试.next
。 编辑: console.log($.mobile.urlHistory.stack);
检查主页是否保留在历史记录中。
【参考方案1】:
在篡改导航时,我经常遇到同样的问题。这一切都归结为 JQM 没有在 DOM 中找到页面,尽管它在那里。您可以通过导航小部件console.log
您将看到 JQM 退出的位置以及退出原因。它通常可以从外部修复,因此无需破解 JQM。
看看最新的 JQM.js here。
寻找这一行$.widget( "mobile.pagecontainer",
,
然后找到change
方法(离得很远)。控制台日志:
console.log("transition A")
this._loadUrl( to, triggerData, settings );
else
console.log("transition B")
this.transition( to, triggerData, settings );
你应该在这里,所以接下来看看load
方法,它是从_loadUrl
调用的。 Load
以 Ajax 调用或转换结束,所以如果你没有得到任何一个,你应该在这里找到原因。控制台content
:
content = this._find( absUrl );
console.log(content)
如果您的页面位于 DOM 中,则应为您的页面设置内容。还有console
就在下面:
// If it isn't a reference to the first content and refers to missing
// embedded content reject the deferred and return
if ( content.length === 0 &&
$.mobile.path.isEmbeddedPage(fileUrl) &&
!$.mobile.path.isFirstPageUrl(fileUrl) )
console.log("if you are here:")
console.log("content is not found = "+ content.length === 0)
console.log("it's NOT the first page = " + !$.mobile.path.isFirstPageUrl(fileUrl))
console.log("it's an embedded page (i believe like a dialog, unlikely) = )"+$.mobile.path.isEmbeddedPage(fileUrl))
deferred.reject( absUrl, settings );
console.log("GOOD BYE")
return;
如果content
为空,请检查_find
方法,您应该在其中找到解决方法的答案。大量控制台并阅读 JQM 的 cmets!:
var fileUrl = this._createFileUrl( absUrl ),
dataUrl = this._createDataUrl( absUrl ),
page, initialContent = this._getInitialContent();
console.log("fileUrl ="+fileUrl)
console.log("dataUrl ="+dataUrl)
page = this.element
.children( "[data-" + this._getNs() +"url='" + dataUrl + "']" );
console.log(page)
您会看到page
是由data-url
而不是id
(!) 确定的。因此,一种解决方法可能是将正确的data-url
添加到您的页面。正确的意思是 JQM 所期望的,而不是可能正确的......另一个问题可能是dataUrl
,所以请检查这是什么以及它是否是您要访问的页面的 url。通过将data-url
设置为我需要的任何内容,我设法解决了我这边的一些问题,从而确保JQM 将在DOM 中找到该页面。继续...
if ( page.length === 0 && dataUrl && !$.mobile.path.isPath( dataUrl ) )
page = this.element.children( $.mobile.path.hashToSelector("#" + dataUrl) )
.attr( "data-" + this._getNs() + "url", dataUrl )
.jqmData( "url", dataUrl );
console.log(page)
console.log(!$.mobile.path.isPath( dataUrl ));
在page
进行第二次推介,如果第一次没有成功。一定要检查第三个参数。再试一次:
if ( page.length === 0 &&
$.mobile.path.isFirstPageUrl( fileUrl ) &&
initialContent &&
initialContent.parent().length )
page = $( initialContent );
console.log(page)
console.log($.mobile.path.isFirstPageUrl( fileUrl ))
console.log(initialContent)
console.log(initialContent.parent().length)
就是这样。除非你的错误是基本的......你应该在这里找到解决方案。让我知道你卡在哪里了。我会尽力帮忙的。
编辑:
可能的解决方法:如果 JQM 的第一页存储 包含 一个主题标签,而它通常不会(因为您从 index.html
之类的东西开始,您可以通过手动删除 JQM 存储在其历史记录中的主题标签来解决这个问题 -仅限第一页。
这只需要在向后转换时完成,所以你需要一个pagebeforechange
的监听器,然后调用它:
// capture only when toPage is an object
if (typeof data.toPage !== "string")
// only when going back!
if (e === undefined)
// only when going back to the first page
if ($.mobile.navigate.history.initialDst &&
window.location.hash !== "")
// clean url
clean_url = window.location.href.split("#")[0];
parsed_url = $.mobile.path.parseUrl(clean_url);
// set in JQM
$.mobile.navigate.history.stack[0].hash = "";
$.mobile.navigate.history.stack[0].url = clean_url;
$.mobile.path.documentUrl = parsed_url;
$.mobile.path.documentBase = parsed_url;
为我工作。您可能需要稍作修改,但原则是remove the hash information on JQMs initial history entry
【讨论】:
这有帮助。我能够追查到的是:使用$.mobile.changePage("pages/login-page.html")
的页面负载弄乱了路由器。 #mainpage
href 被浏览器读取为login-page.html#mainpage
中的标签,因此我的路由路径忽略了它。我不知道从这里去哪里 - 从技术上讲,它是那个页面,但骨干似乎希望它全部从同一页面引用,或者我不知道我在做什么。两者都有可能。
修复了它。它还可以让我自定义如何编写我的标签,这样他们就不必知道文件结构。
是的,很漂亮,甚至没有 hack :-)。很高兴它有帮助。
在我忘记之前,您不能在主题标签中使用 ?
,因此您需要在主题标签中使用其他东西来表示 foo(我使用的是 ::
)以上是关于如何使用 Backbone.js 在 changePage 后显示 JQuery Mobile 主页面的主要内容,如果未能解决你的问题,请参考以下文章
如何开始使用 Backbone.js 和 Rails 3.1
Backbone.js - 如何在模板中使用自定义模型属性?