问题
I am trying to write my first single-page application. The idea is to have 1 HTML file that contains many <div>
tags; where each <div>
represents a single web "page". Then the application just shows 1 <div>
at a time, and hides the others. In this way, as users navigate my app, I'm really just showing/hiding different "page" divs, and giving the illusion of a single page app.
Additional requirements are:
- This is an HTML5 app
- Each page div must map too its own bookmarkable URL (
http://myapp.example.com/#fizz
,http://myapp.example.com/#buzz
, etc.) - Singe each page div is bookmarkable, the app must work with the HTML5 history api
I decided on using Crossroads for routing, and Hasher for History. The other lead contender was AngularJS, but in the end I decided against AngularJS because it was too heavyweight for what I'm trying to do here, and seemed to have a steeper learning curve associated with it.
So far, my project has the following directory structure:
myapp/
index.html
myapp.js
myapp.css
signals.min.js <-- Required by both Crossroads and Hasher
crossroads.min.js
hasher.min.js
The JSFiddle containing my index.html
, myapp.css
and myapp.js
files is here:
http://jsfiddle.net/Sxfms/2/
The idea is that the user can click one of the links in the "navbar" ("Home", "About", "Contact") and be brought to the "page" (div) representing that particular page.
As you can see, the default "page" should be HOME
, meaning this is the only div you should be able to see. But all the page divs are visible, and none are hidden. And until I can get the page divs showing/hiding correctly, I can't really test routing/history functionality. Have I configured Crossroads/Hasher wrong somehow?
回答1:
I think there is a solution for your requirements. It is a really easy, lightweight approach without the need of any javascript just with the power of CSS. ;-)
The key of the whole approach is the CSS pseudo-class selector :target
.
So let me first explain the concept of :target
: The pseudo selector matches when the fragment identifier (or hash, #content for instance) in the URL and the id
of an HTML element are the same. If we have a URL like http://www.example.com/hallo.html#content
and an element with the id="content"
the selector #content:target { ... }
would match.
You can´t really see the URL in this fiddel, but you will in another example. Her is the code of the fiddle:
HTML:
<a href="#content">content</a>
<div id="content">
Markup is poetry!
</div>
CSS:
#content {
border: 1px solid black;
padding: 20px;
}
#content:target {
background: lightblue;
}
The :target
approach leads to this stripped down example to explain the page-navigation-idea: http://jsfiddle.net/Cxr73/1/ Again you can´t really see the URLs with the fragment identifier.
HTML:
<a href="#div1">div1</a>
<a href="#div2">div2</a>
<a href="#div3">div3</a>
<div id="div2">
<div id="div3">
<div class="div1Inner">content div1</div>
<div class="div2Inner">content div2</div>
<div class="div3Inner">content div3</div>
</div>
</div>
CSS:
.div2Inner, .div3Inner,
#div2:target .div1Inner, #div3:target .div1Inner {
display: none;
}
#div2:target .div2Inner, #div3:target .div3Inner {
display: block;
}
Hide all div
s that should not be displayed at first: .div2Inner, .div3Inner { display: none;}
. So just <div class="div1Inner">content div1</div>
is visible. Show the corresponding div
when the fragment identifier is part of the URL: #div2:target .div2Inner, #div3:target .div3Inner {display: block;}
. In the end you have to hide div1
when div2
or div3
are visible: #div2:target .div1Inner, #div3:target .div1Inner { display: none; }
. Combine the first and the last CSS selector and you get to the CSS shown above.
Some recommendations on your markup:
- As recommended by the HTML5 spec (4.2.5.5 Specifying the document's character encoding), add your charset declaration early to avoid a potential encoding-related security issue in IE. It should come in the first 1024 bytes.
- The
<center>
element was deprecated because it defines the presentation of its contents. For this purposes we have CSS. - You are writing an HTML5 app, so throw in some more semantic markup, elements like:
nav
,header
,section
,footer
, etc.
Here you have the final approach of my ideas, with your CSS plus the :target
selectors (starts at line 600) and what I consider a clean markup:
Fiddle: http://jsfiddle.net/Cxr73/2/
To finally see the fragment identifier plus the :target
in action and for test purposes another URL: DEMO ... this demo will disappear in a few days, but the fiddle will stay.
I think that pretty much matches all your needs. Have fun!
来源:https://stackoverflow.com/questions/23969266/single-page-application-routing-w-crossroads-hasher-by-example