How to implement my own history stack in a single page mobile web application?

只愿长相守 提交于 2019-11-30 00:09:14

I don't know about backbone.js1, but I have helped develop a mobile application which had to implement exactly this behavior in html5, so I should be able go give some good advice:

First of all it's good to know that the history.pushState function exists. The big problem with it though is that it is supported up to android 2.3, but not on android 3 till android 4.0.3. As kiranvj points out correctly this can be solved by using the popular history.js library which provides a polyfill solution for the lack of the history functionality.

Now, getting to your actual problem, the way I implemented the history direction animations was by adding data to the pushState function ( history.pushState(data,title,url) ) with which I identified the logical position of the page. In my application I wasn't only limited to a horizontal bar, but in your case you would keep track of position where any new loaded page get's a position which is one higher then your current page. E.g.

History.pushState({position:History.getState().data.position+1},"Your title","Your URL");

Next, when the window.onstatechange or window.onanchorchange event triggers you observe whether the position is higher or lower than your current page (e.g. by using the history.js History.getState() function which I used above) and depending on this you decide in which direction to move (lower is to the left, and higher is to the right), as is illustrated by the image below:

You will also note that I already assumed on the first page that you have {position:1}, whereas normally the first page will have no state information. The way this can be achieved is by using history.replaceState which replaces the current empty state with a more informative state. Alternatively you can also check for an empty state on any of the previously mentioned events and if it's empty you assume it to be the left most one ({position:1}).

Hope this helps and if you have any additional questions feel free to ask.

Please note that this answer assumes you are using history.js and you would need to listen to slightly different events (such as onpopstate) and use slightly different structures (history rather than History) if you would want to build your own solution.

It is also useful to note that it is possible to build this with your own queue array which gives you a lot more control, but will not work in combination with the browser's back button. This is a big issue with browser sites, however is far easier in case you are building a cordova (a.k.a. phonegap) web application.


1 Just read about it and it appears to do some history handling of its own, which might make it more complex to integrate the technique described above.

If you're working on a true single-page app, why not you set up an array to hold history urls in a js variable (as opposed to relying on something like history.pushState and its support)?

Whenever a new page is navigated to, you can push its url into the array, whenever a "back" button is pressed, you can retrieve the url needed as far back as you want. This will work perfectly as long as you correctly discard urls when the user goes back a few steps and then navigates to a new link.

I've never tried implementing this to be used for page history, but this worked perfectly well for in-page undo-redo logic.

Update:

After further research, the approach above would not work for a page reload as it would be an action occuring outside of history handling available through JS. It would still work for tracking back/forward transitions, but such history will be lost on navigating to a url external to the app or a page refresh. David Mulder's answer seems to lack this limitation by relying on browser-level history that persists outside of the page scope.

kiranvj

I had the same issue when working with Zepto on mobile with single page - multiple views.

Initially I used html5 statechange and onhashchange. It all have some issues in one or other mobile device. Finally I used Zepto history plugin from here https://github.com/browserstate/history.js

It somewhat solved most of the issues. Try it, it will be useful, it handle html4 and html5 features wherever possible.

Use this thing in single page mobile application this will allow to the history and move the user to back.

function onBackKeyDown() {
    history.go(-1);
    navigator.app.backHistory();
}

Sammy.js's v.6.x branch (the one that relies just on hash changes) is a perfect, simplest, most browser-compatible approach to tracking history. There, history is not tracked at all, as Sammy just watches for hashchange.

Relying on "#/slide/123" allows you to support hard page reloads, and simplifies the work

Peel off the last part (slide number) on each page view, push into global. On new route, see if number is more or less than what is stored in global and do the correct (left or right) animation. If global is undefined, no animation.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!