在 jQuery Mobile 和 PhoneGap 中创建模板化/持久化页眉/页脚模板
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9152446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Creating templated/persistant header/footer template in jQuery Mobile and PhoneGap
提问by Luke Shaheen
I'm diving into writing a mobile app with jQuery Mobile/PhoneGap. I'm using this sample templateto start from, which uses HTML/JS to create the pages. Rather than have all the <page>
tags in one single html file, he's got it split up so it's easier to edit.
我正在研究使用 jQuery Mobile/PhoneGap 编写移动应用程序。我使用这个示例模板开始,它使用 HTML/JS 来创建页面。他没有将所有<page>
标签放在一个单一的 html 文件中,而是将其拆分,以便更容易编辑。
Since I will have a separate file for each page, what's the best way to include the tempated header/footer?I've only seen it where you need to copy and paste the whole footer->navbar code into each HTML page. This doesn't seem like it should be. For example, if you want to change one menu item, you need to go into each page and change it.
由于我将为每个页面创建一个单独的文件,因此包含带模板的页眉/页脚的最佳方法是什么?我只在您需要将整个页脚-> 导航栏代码复制并粘贴到每个 HTML 页面的地方看到它。这似乎不应该是。例如,如果要更改一个菜单项,则需要进入每个页面并进行更改。
What's the solution that I'm missing?
我缺少的解决方案是什么?
Maybe I'm just not understanding jQuery Mobile. For example, their sidebar they use for their docs - is that sidebar code copy and pasted onto each page? That doesn't make sense. It's the same idea as the question I'm asking here about the footer.
也许我只是不了解 jQuery Mobile。例如,他们用于文档的侧边栏 - 侧边栏代码是否复制并粘贴到每个页面上?那没有意义。这与我在这里提出的有关页脚的问题的想法相同。
http://jquerymobile.com/test/docs/pages/page-cache.html
http://jquerymobile.com/test/docs/pages/page-cache.html
This is what I've got that doesn't seem right (and $.live('pageinit')
isn't working). This HTML is what goes on each HTML page:
这就是我所拥有的似乎不正确的(并且$.live('pageinit')
不起作用)。这个 HTML 是每个 HTML 页面上的内容:
<div id="mainFooter" data-position="fixed" data-id="mainFooter" data-role="footer" class="ui-footer ui-bar-a ui-footer-fixed fade ui-fixed-inline" role="contentinfo" style="top: 58px;">
And the JS
和 JS
$.live('pageinit', function (event) {
displayFooter();
});
function displayFooter() {
$('#mainFooter').html('<div data-role="navbar" class="nav-glyphish-example" data-grid="d">' +
'<ul>' +
'<li><a href="#" id="menuitem1" data-icon="custom">Menu Item 1</a></li>' +
'<li><a href="#" id="menuitem2" data-icon="custom">Menu Item 2</a></li>' +
'<li><a href="#" id="menuitem3" data-icon="custom">Menu Item 3</a></li>' +
'</ul>' +
'</div>');
}
采纳答案by ostroon
I've been trying to tackle this problem for a few days now and I've gotten really close to the solution. I use the following HTML:
我已经尝试解决这个问题几天了,我已经非常接近解决方案了。我使用以下 HTML:
<body>
<div data-role="page" id="page">
<div data-role="header">
<h1 id="title">Title</h1>
</div><!-- /header -->
<div data-role="content" id="content">
<p>Loading...</p>
</div><!-- /content -->
<div data-role="footer" id="footer" data-position="fixed">
<div data-role="navbar" id="navbar">
</div>
</div><!-- /footer -->
</div><!-- /page -->
</body>
And I've created the following functions to load the menu/content using ajax:
我创建了以下函数来使用 ajax 加载菜单/内容:
$(document).on('pageinit', "#page", function() {
// for example: displayFooter();
loadContent("main");
loadMenu("default");
});
function loadContent(location) {
return $('#content').load("views/content/"+location+".html", function() {
$(this).trigger('create');
});
}
function loadMenu(location) {
$("#menu").remove();
$("#navbar").remove();
$("#footer").html('<div data-role="navbar" id="navbar">');
$("#navbar").html('<ul id="menu"></ul>');
$("#menu").load("views/menus/"+location+".html", function() { $("#menu").parent().navbar(); });
return true;
}
The .trigger('create');
and .navbar();
are the methods required to keep the JQM styling correct, however, there's still one little bug. The position of the menu (which is set using css top: ...px) is sometimes not correct and moves itself to the correct position after the first tap. Really close though!
该.trigger('create');
和.navbar();
是保持JQM造型正确所需的方法,但是,还是有一个小虫子。菜单的位置(使用 css top: ...px 设置)有时不正确,并且在第一次点击后移动到正确的位置。不过真的很近!
Edit:By setting #footer
to position: fixed;
the minor bug I mentioned above is gone. Also, it's easy to make a method that calculates the top
(in px) for the #footer
if the position caused by the top
value by JQM is incorrect.
编辑:通过设置#footer
到position: fixed;
我上面提到的小错误不见了。此外,如果由 JQM的值引起的位置不正确,则很容易制作一种计算top
(以 px 为单位)的方法。#footer
top
回答by bmurmistro
Something like this:
像这样的东西:
function getText() {
//return footer text here
}
$("div:jqmData(role='page')").live("pagebeforecreate",function() {
// get find the footer of the page
var $footer =$(this).page().find('div:jqmData(role="footer")')
// insert it where you want it...
}
you could just define the role=footer in the getText and just check to see if it's defined... if not then add it.
您可以在 getText 中定义 role=footer 并检查它是否已定义...如果没有,则添加它。
回答by Yacine Filali
If you really want to do this properly, you need to look into a js framework like Thorax or JavascriptMVC.
如果你真的想正确地做到这一点,你需要研究像 Thorax 或 JavascriptMVC 这样的 js 框架。
In a JMVC app, you could do this from any view:
在 JMVC 应用程序中,您可以从任何视图执行此操作:
<div data-role="page">
<%== $.View('./header.ejs') %>
<div data-role="content">
...
</div>
<%== $.View('./footer.ejs') %>
</div>
jQuery Mobile is really only useful for progressive markup enhancement and styling for mobile devices. For the actual MVC part you need an MVC framework.
jQuery Mobile 实际上只对移动设备的渐进式标记增强和样式有用。对于实际的 MVC 部分,您需要一个 MVC 框架。
The examples for jQuery Mobile are also mostly geared for building mobile web sites which since they fetch pages from a server assume your code reuse is happening server side. A phonegap app is a whole nother beast since you will be generating these pages on the fly or from local static files. This is were the MVC framework comes in as you would be building your pages using controllers, views, view helpers, and model classes. You tie all that into jQuery mobile by listening to the pagebeforeshow event as shown on the jQm documentation page on scripting pages
jQuery Mobile 的示例也主要用于构建移动网站,因为它们从服务器获取页面,假设您的代码重用发生在服务器端。phonegap 应用程序完全不同,因为您将动态生成这些页面或从本地静态文件生成这些页面。这是 MVC 框架的出现,因为您将使用控制器、视图、视图助手和模型类构建页面。您可以通过侦听 pagebeforeshow 事件将所有这些与 jQuery mobile 联系起来,如脚本页面上的 jQm 文档页面所示
回答by frequent
Depends how you load the respective pages.
取决于您如何加载相应的页面。
If you use rel="external" - no AJAX, each page will be reloaded completely.
如果您使用 rel="external" - 没有 AJAX,每个页面都将被完全重新加载。
If you use regular JQM - AJAX, JQM will grab the page and attach it to your existing DOM. Think of your first page as your "anchor" page, which all subsequent pages are added/removed.
如果您使用常规 JQM - AJAX,JQM 将抓取页面并将其附加到您现有的 DOM。将您的第一页视为您的“锚点”页面,添加/删除所有后续页面。
In the 2nd case you could specify a data-append-to-all-pages="true" attribute on elements you want to have on every page.
在第二种情况下,您可以在您希望在每个页面上拥有的元素上指定 data-append-to-all-pages="true" 属性。
Then just listen to the respective event (pagebeforeshow?) and add elements with the above label to the new page before it's shown. This way elements would only have to be set on the first page and then automatically be added to any subsequent page being pulled in and added to the DOM.
然后只需收听相应的事件(pagebeforeshow?)并在显示之前将具有上述标签的元素添加到新页面。通过这种方式,元素只需在第一页上设置,然后自动添加到任何被拉入并添加到 DOM 的后续页面。
I'm looking into this right now with a login form, which I need on every page outside the login and have to avoid ending up with duplicate input#someID.
我现在正在使用一个登录表单来研究这个问题,我需要在登录之外的每个页面上使用它,并且必须避免以重复的 input#someID 结束。
EDIT - possible solution
编辑 - 可能的解决方案
Put the respective element on the first page and add unique attributes, like so:
将相应的元素放在第一页并添加独特的属性,如下所示:
<div data-role="navbar" data-unique="true" data-unique-id="log">
// full navbar
</div>
All other pages just get the unique element container
所有其他页面只获得唯一的元素容器
<div data-role="navbar" data-unique="true" data-unique-id="log"></div>
Then use this script:
然后使用这个脚本:
$('div:jqmData(role="page")').live('pagebeforehide', function(e, data) {
// check page you are leaving for unique items
$(this).find('div:jqmData(unique="true")').each(function(){
// more or less 1:1 stickyFooter
var uniqueID = $(this).jqmData("unique-id"),
nextPage = data.nextPage,
nextUnique = nextPage && nextPage.find( "div:jqmData(unique-id='"+uniqueID+"')" ),
nextMatches = nextUnique.length && nextUnique.jqmData('unique-id') === uniqueID;
// if unique items on previous and new page are matching
if ( uniqueID && nextMatches ) {
nextUnique.replaceWith( uniqueID );
$(this).jqmData("unique-id").empty();
}
});
});
Of course this would mean you need the unique container on every page. But then you would just carry the content of it along as you traverse through the app. Should work for me and avoid having the same login form 2+ times inside the DOM.
当然,这意味着您需要在每个页面上都有唯一的容器。但是,当您遍历应用程序时,您只需随身携带它的内容。应该对我有用,并避免在 DOM 中使用相同的登录表单 2 次以上。
Plus you would be free to edit it's contents for example adding active class.
另外,您可以自由编辑它的内容,例如添加活动类。
回答by imaginethepoet
We haven't found a good way to do this yet either. So we are actually handling this dynamically in our custom js file. Looking for the closing container - and then dynamically appending the footer after the last content div closes.
我们也还没有找到一个好的方法来做到这一点。所以我们实际上是在我们的自定义 js 文件中动态处理这个。寻找关闭容器 - 然后在最后一个内容 div 关闭后动态附加页脚。
回答by Clarence Liu
Don't use pageinit, the events that you should listen for are pagecreate and pageshow, pagecreate gets called the first time a page is loaded, but not when you navigate back to the page, e.g. on back button. Whereas pageshow fires everytime a page is shown, so just bind a live listener to the pageshow event for every page where you add your footer (assuming your footer may change, otherwise use pagecreate).
不要使用pageinit,您应该监听的事件是pagecreate 和pageshow,pagecreate 在第一次加载页面时被调用,但在您导航回页面时不会被调用,例如在后退按钮上。而每次显示页面时都会触发 pageshow,因此只需将一个实时侦听器绑定到添加页脚的每个页面的 pageshow 事件(假设您的页脚可能会更改,否则使用 pagecreate)。
I have a longer example that shows you how to bind to the event properly in another question: https://stackoverflow.com/a/9085014/737023
我有一个更长的示例,向您展示如何在另一个问题中正确绑定到事件:https: //stackoverflow.com/a/9085014/737023
And yes a great solution is just to use a PHP/CF include, which is what I use instead of JS.
是的,一个很好的解决方案是使用 PHP/CF 包含,这是我使用的而不是 JS。
EDITMy bad, seems pageinit is now used instead of pagecreate (see here), but it still stands that pageshow fires every time a page is shown - so you can use those as you need
编辑我的错,现在似乎使用 pageinit 而不是 pagecreate (see here),但它仍然表明每次显示页面时都会触发 pageshow - 因此您可以根据需要使用它们