jQuery Mobile is a front-end development framework for creating mobile web applications.
jQuery Mobile can be used on smartphones and tablets.
jQuery Mobile uses HTML5 & CSS3 minimal scripts to layout web pages.
Recently, the company’s web app project has given me the honor to keep contacting and learning jQuery Mobile. This is indeed a very good mobile development library that helps engineers who are good at web development to quickly get started and build their own mobile applications. But in the past two days, I encountered a problem, which made me check a lot of information but could not find a good solution. In the end, I was forced to read the source code of jQuery Mobile and write an extension to solve it. Please let me explain below.
Problem Description
Suppose there are three pages in the project, namely main.html, test1.html, test2.html (hereinafter referred to as main, test1, test2 respectively), where the main page contains a link to the test1 page (i.e. a tag), test1 has a link with the attribute data-rel="back" and a link to test2, and test2 has only one link with the attribute data-rel="back". After main transfers to test1, click the back link to return to main (equivalent to clicking the browser's return button). There is no need to resend the get request; but when test1 transfers to test2, when you click the back link on the test2 page and want to return to test1, it will resend a get request. get request. The problem caused by this is that all operations performed by test1 will be invalid after test2 returns. For example, A is a paginated list page. If you turn to the second page and then redirect to B, then when you return to A, you will not be able to move to the second page.
Cause Analysis
I first used firebug to look at the structure of the html, and found that jQuery Mobile would add main and test1 to the page structure. When it switches from test1 to test2, test1 will be automatically deleted, so that the dom tree only contains main and test2, so when test2 returns test1, a get request will be sent. Does that mean that as long as the historical pages can be cached in the dom (just like main and test1), this problem can be solved.
Solve the problem
After some searching, I saw a description of "Caching pages in the DOM" on the jQuery Mobile official website:
Caching pages in the DOM
To keep all previously-visited pages in the DOM, set the domCache option on the page plugin to true, like this:
$.mobile.page.prototype.options.domCache = true;
Alternatively, to cache just a particular page, you can add the data-dom-cache="true" attribute to the page's container:
You can see from this quotation that these three methods can cache the page into the dom, so I used the second method, which is to add data-dom-cache=” to the div of the page. true" attribute, but the following two problems occurred:
1. As shown in the figure below, when my access path is main->test1->test2->test1 (test2 is returned by history.back()), you can see with firebug that test2 is still Exists in the DOM, the result is as described in the red part: the DOM will become very large, resulting in page slowdown and memory errors on some devices.
2. When I have such a page, it displays different content through different parameters, and there is a js script on the page that will do some processing on the elements on the page, and our common way is to use id. To obtain the target element, since we use cache to cache the page, it will cause js events or operation confusion. For example, here I added a test1_1 page. Its content is almost the same as test1. They both have divs with the same ID and buttons with the same event processing. What this event does is to add content to this div. When the access path is main ->test1->test1_1, click the button on test1_1, you will find that this event does not seem to be triggered. In fact, it has been triggered, but the content is added to the div in test1, as shown in the figure below
So for most current applications, this solution is not advisable unless you manage the life cycle of the page in the DOM yourself.
Optimization plan
Through the above experiment, I also know that to meet my needs, I can only manage the life cycle of the page in the DOM myself. Then it involves a question: When will the page expire (that is, be deleted from the dom)? According to my needs, when returning from test2 to test1, test2 should be deleted from the dom. Similarly, when returning to main from test1, test1 should be deleted from the dom. If you navigate from main to test1 again, you have to initiate a get request. I think this is reasonable because the user will not think that clicking the link to a new page requires caching. So I should delete the history after the page before or after it is displayed, so I did the deletion operation during pagebeforeshow and pageshow, that is, the following script (plug-in form):
(function($, undefined) { $.fn.subpage = function(options) { $(document).bind( "pagebeforeshow", function() { var forword = $.mobile.urlHistory.getNext(); if (forword) { var dataUrl = forword.url; var forwordPage=$.mobile.pageContainer .children(":jqmData(url='" + dataUrl + "')"); if(forwordPage){ forwordPage.remove(); } } $.mobile.urlHistory.clearForward(); }); }; $(document).bind("pagecreate create", function(e) { $(":jqmData(role='page')", e.target).subpage(); }); })(jQuery);
The result was counterproductive. When the page was returned, a js script error occurred, as shown below:
So what’s the reason? If this incident is not handled, then where should it be handled? So I carefully studied the jQuery Mobile source code and found the following paragraph:
transitionPages( toPage, fromPage, settings.transition, settings.reverse ) .done(function() { removeActiveLinkClass(); //if there's a duplicateCachedPage, remove it from the DOM now that it's hidden if ( settings.duplicateCachedPage ) { settings.duplicateCachedPage.remove(); } //remove initial build class (only present on first pageshow) $html.removeClass( "ui-mobile-rendering" ); releasePageTransitionLock(); // Let listeners know we're all done changing the current page. mpc.trigger( "pagechange", triggerData ); });
After the page is switched, the pagechange event will be triggered, so I changed pagebeforeshow to pagechange. Everything ran as expected and there were no errors. Finally, I was done.
Summary
When using this plug-in, please pay attention to the following points:
1. You must quote jquery and jquery mobile script files before quoting the script;
2. Data-dom-cache="true" must be added to the page.
The above is the relevant instructions introduced by the editor to return jQuery Mobile pages without re-getting. I hope it will be helpful to everyone!