1, Problem Description:
1. In the development of mobile terminal, the list page is generally used to add the content of the next page to the end of the current list page to realize the paging function. When sliding down to a page, click a piece of information to enter the details page, and then click the return of the details page to return to the previous list page. At this time, the list page refreshes and returns to the home page, and the list data does not There is a place to locate the data that was clicked before.
2. To solve this problem, the previous development also considered that the return button on the page is set to onclick = "javascript: history. Back (- 1); ", the online description of this writing method is to return to the previous page without refreshing the page, but this writing method is only effective for some browsers. Through the test, it is found that this writing method is only effective for safari and uc browsers of Apple mobile phone, and other browsers will force the content of the previous page to refresh the list page in the current problem. Therefore, it is verified that this problem only occurs on Android mobile phone, but not on Apple mobile phone Of the problem. (whether it's clicking the back button on the page or the back button of Android phone, or Apple phone swiping the screen from left to right to return to the previous page, it's the same phenomenon. Apple phone has no problem, Android phone has problems.)
2, Solution:
1. In view of this problem, whether using the front-end framework such as vue or the native front-end technologies such as js and jQuery, they are the same solution, that is, before clicking to enter the detail page, cache the current list data, search conditions and the sign of returning to the list page from the detail page, and then judge whether to return from the detail page when entering the list page again If it is, the data echo from the cache can be obtained.
2. For the development of mobile page by H5+jQuery, sessionStorage, an important object in js, is used to cache data. The specific usage of sessionStorage is as follows:
(1) , sessionStorage.setItem('key','value'); / / cache data
(2) , var data = sessionStorage.getItem('key '); / / get data from sessionStorage
(3) , sessionStorage.removeItem('key '); / / delete a cache data
(4) , sessionStorage.clear(); / / clear all cached data
3. H5+jQuery+sessionStorage+bscroll.js(bscroll implements page scrolling up and down, that is, data positioning in this problem) solves the main implementation code content analysis of this problem (details cache content processing is handled according to the actual situation, here only the main business logic is described):
(1) First, extract the common method, that is, the method of sessionStorage caching data, such as code:
/ / cacheKey cache key cacheValue cache content json structure
function addToCache(cacheKey,cacheValue){
cacheValue = JSON.stringify(cacheValue); / / convert JavaScript objects to strings
var allCacheData = sessionStorage.getItem(cacheKey);
if(allCacheData != null){
allCacheData = allCacheData.substr(0, allCacheData.length - 1)+","+cacheValue.substr(1, cacheValue.length); / / String splicing in json format
} else {
allCacheData = cacheValue;
}
sessionStorage.setItem(cacheKey,allCacheData);
}
(2) . when entering the list page for data initialization for the first time or querying data according to conditions to obtain list data, delete the previous cache first, and then cache new data, such as code:
/ / for a new access, clear all related caches
sessionStorage.removeItem("cacheKey");
sessionStorage.removeItem("articleId");
/ / add a new access data
addToCache("cacheKey",result.data);
/ / add a new filter
sessionStorage.setItem('selectData',JSON.stringify(data));
(3) When you scroll down to get the next page data, you should also cache the new data currently obtained, such as: addToCache("cacheKey",result.data);
(4) , add click event to each list data, and cache the unique identifier when data click Details jump, so that it can be returned from the details page when it is returned to the list page. The code is as follows:
function openUrl(url,id){
sessionStorage.setItem("articleId",id); / / the id of each data is unique and can be used as an identifier
window.location=url;
}
(5) , left back is also the most important step. In the method of initializing the list data, make branch judgment. If the operation returned from the detail page is to obtain the data from the cache, otherwise, go to the normal way to obtain the data from the database. The code example is as follows:
$(function() {
initData(); / / initializes other dictionary values on the page, not related to this problem
/ / judge whether to return the operation from the details page according to the articleId
var articleId = sessionStorage.getItem("articleId");
var cacheData = sessionStorage.getItem("cacheKey");
If (articleid! = null & & cachedata! = null) {/ / returned from the details page and the list cache data is not empty
sessionStorage.removeItem("articleId"); / / please clean it up once you use it
/ / get filter condition data from cache for echo
var selectData = sessionStorage.getItem('selectData');
var sd = JSON.parse(selectData)
$('#dbName').val(sd.dbName);
$('#condition').val(sd.conditionVal);
$('.divselect1 span').html(sd.condition);
/ / get the height of the screen
var wid = $(window).height();
$(".rank-box").height(wid - 130);
/ / retrieve the list data from the cache for echo
var result = {};
result.data=JSON.parse(cacheData);//JSON.parse(cacheData) converts a json string to a js object
$(".listul").html(template("view_searchList", result));
/ / locate the returned data location
Var offset = $('×' + articleid). Offset(). Top; / / the offset distance between the current data and the upper boundary
scroll.refresh();
scroll.scrollTo(0,-offset+130, 0);//x,y,timeType Y represents the distance of downward offset
{/ / else {/ / does not walk the cache. Normal logic obtains data from the database for display
var wid = $(window).height();
$(".rank-box").height(wid - 130);
/ / if you want to jump from more buttons on the home page, get the corresponding data
var dbName = '${dbName!}';
if (dbName != '') {
var data = {};
data.dbName = dbName;
data.sport = '${sport!}';
data.category = '${category!}';
data.page = 0;
isreload = true;
getData(data);
//$("#dbName").find("option:contains('${dbName!}')").attr("selected",true);
$("#dbName").val(dbName);
}
}
})
3, Source file for reference
1,
<!DOCTYPE HTML> <html> <head> <base href="../../../"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0,user-scalable=no"> <meta http-equiv="Cache-Control" content="max-age=0"> <meta name="apple-touch-fullscreen" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link rel="stylesheet" href="gtqb/iconfont/iconfont.css" /> <link rel="stylesheet" type="text/css" href="gtqb/css/dj_phone.css"> <script type="text/javascript" src="gtqb/js/jquery-1.7.2.js"></script> <script type="text/javascript" src="gtqb/js/dj_phone.js"></script> <!-- <script type="text/javascript" src="gtqb/js/scroll.js"></script> --> <script type="text/javascript" src="js/config.js"></script> <script src="gtqb/js/bscroll.js"></script> <title>Search list</title> </head> <body> <!-- Head start --> <div class="dj-headInforBox"> <a class="back_left" onclick="goToIndex()"></a> <select id="dbName"> <option value="qb">whole</option> <option value="qbxx">Information intelligence</option> <!-- <option value="yjbg">research report</option> --> <option value="mtkb">Public opinion Bulletin</option> <option value="ydsp">Competition video</option> </select> </div> <!-- End of head --> <!-- Search box start --> <div class="dj-searchBox"> <!-- <div id="sKeyWrap0"> --> <!-- <div class="fl jajianBox"> <div class="add fl"></div> <div class="minus fl"></div> </div> --> <div class="selectBoxBig"> <div class="divselect1"> <span>Title</span> <i></i> </div> <ul class="selectBoxs1"> <li value="">Title</li> <li value="">author</li> </ul> <em></em> </div> <!-- </div> --> <div id="inputbox" class="fl"> <input type="text" id="condition" /><i class="iconfont icon-jiansuo" onclick="select()"></i> </div> <a class="searchBtn" id="sxBtn">screen</a> </div> <!-- End of search box --> <!-- List start --> <div class="dj-dataBoxCon rank-box"> <div class="pxzbList"> <ul class="listul"> <!-- list --> </ul> <div class="bottom-tip" style="display: none"> <span class="loading-hook">No more data</span> </div> </div> </div> <!-- End of list --> <!-- Filter box start --> <div class="select_tkBox" style="display: none;"> <div class="select_tkCon"> <div class="tk_infor"> <ul> <li> <h4>Sport event</h4> <div class="sport"> <div class="tk_inforCon "> <a>Athletics</a> </div> <div class="tk_infor_more"> <a>More>></a> </div> </div> </li> <li> <h4>Country/region</h4> <div class="country"> <div class="tk_inforCon "> <a>U.S.A</a> </div> <div class="tk_infor_more"> <a>More>></a> </div> </div> </li> <li> <h4>time</h4> <div class="time"> <div class="tk_inforCon "> <a>2020</a> <a>2019</a> <a>2018</a> <a>2017</a> <a>2016</a> <a>2015</a> <a>2014</a> <a>2013</a> <a>2012</a> </div> <div class="tk_infor_more"> <a>More>></a> </div> </div> </li> <li> <h4>Information category</h4> <div class="category"> <div class="tk_inforCon "> <a>State of readiness</a> </div> <div class="tk_infor_more"> <a>More>></a> </div> </div> </li> </ul> <div class="tk_btnBox"> <a onclick="toSelect()">Determine</a> <a class="off" id="off">Close</a> </div> </div> </div> </div> <!-- <input type="hidden" value="0" name="page" id="page"> --> </body> <script type="text/html" id="view_time"> <div class="tk_inforCon "> {{each time item i}} {{if i < 10}} <a onclick="selection(this)" id="{{item}}" class="{{item.isSelect}}">{{item.name}}</a> {{else}} <a onclick="selection(this)" id="{{item}}" class="none num {{item.isSelect}}">{{item.name}}</a> {{/if}} {{/each}} </div> <div class="tk_infor_more"> <a onclick="toMore(this)" class="more">More>></a> </div> </script> <script type="text/html" id="view_xxlb"> <div class="tk_inforCon "> {{each xxlb item i}} <a onclick="selection(this)" id="{{item.code}}" class="{{item.isSelect}}" >{{item.name}}</a> {{/each}} </div> </script> <script type="text/html" id="view_ydxm"> <div class="tk_inforCon "> {{each ydxm item i}} <a onclick="selection(this)" id="{{item.code}}" class="{{item.isSelect}} {{if i >= 10}} none num {{/if}} ">{{item.name}}</a> {{/each}} </div> <div class="tk_infor_more"> <a onclick="toMore(this)" class="more">More>></a> </div> </script> <script type="text/html" id="view_guojia"> <div class="tk_inforCon "> {{each guojia item i}} {{if i < 10}} <a onclick="selection(this)" class="{{item.isSelect}}" id="{{item.code}}">{{item.name}}</a> {{else}} <a onclick="selection(this)" id="{{item.code}}" class="none num {{item.isSelect}}">{{item.name}}</a> {{/if}} {{/each}} </div> <div class="tk_infor_more"> <a onclick="toMore(this)" class="more">More>></a> </div> </script> <script type="text/html" id="view_searchList"> {{each data item i}} <li> {{if item.tablename == 'VIDEOINFO_METADATA'}} <a href="" onclick="openUrl('{{item.url}}','{{item.sys_fld_sysid}}')" id="{{item.sys_fld_sysid}}"> <div class="fl pxzbWord"> <h2>{{item.Title}}</h2> <div class="pxzbWordRe"> <span>{{item.Release date}}</span> <span>{{item.author}}</span> </div> </div> <div class="fr pxzbPic"> {{if item.tflag=="0"}} <img src="{{item.filePath}}"/> {{/if}} {{if item.tflag=="1"}} <img src="/review/getFile?fileName={{item.fileName}}&filePath={{item.filePath}}"/> {{/if}} </div> </a> {{else}} <a onclick="openUrl('{{item.url}}','{{item.sys_fld_sysid}}')" id="{{item.sys_fld_sysid}}"> <div class="fl pxzbWord pxzbWord100"> <h2>{{item.Title}}</h2> <div class="zhaiyao" >{{item.abstract}}</div> <div class="pxzbWordRe pxzbWord100Re"> <span>{{item.Release date}}</span> <span class="auther">{{item.author}}</span> </div> </div> </a> {{/if}} </li> {{/each}} </script> <script type="text/javascript"> var page = 0; var isreload = true; var rankBox = document.querySelector(".rank-box"); var scroll = new BScroll(rankBox, { probeType : 1, click : true, }); $(function() { initData(); var articleId = sessionStorage.getItem("articleId"); var cacheData = sessionStorage.getItem("cacheKey"); if(articleId != null && cacheData != null){ //Returned from details page and the list cache data is not empty sessionStorage.removeItem("articleId");//Take care to clean it up after one use var selectData = sessionStorage.getItem('selectData'); var sd = JSON.parse(selectData) $('#dbName').val(sd.dbName); $('#condition').val(sd.conditionVal); $('.divselect1 span').html(sd.condition); var wid = $(window).height(); $(".rank-box").height(wid - 130); var result = {}; result.data=JSON.parse(cacheData); $(".listul").html(template("view_searchList", result)); var offset = $('#'+ articleId).offset().top; / / the offset distance between the current data and the upper boundary scroll.refresh(); scroll.scrollTo(0,-offset+130, 0);//x. Y, timetype Y represents the distance of the downward offset }else { var wid = $(window).height(); $(".rank-box").height(wid - 130); //If you jump from more buttons on the home page, you can get the corresponding data var dbName = '${dbName!}'; if (dbName != '') { var data = {}; data.dbName = dbName; data.sport = '${sport!}'; data.category = '${category!}'; data.page = 0; isreload = true; getData(data); //$("#dbName").find("option:contains('${dbName!}')").attr("selected",true); $("#dbName").val(dbName); } } }) function selection(e) { if ($(e).hasClass("selected")) { $(e).removeClass("selected"); } else { $(e).parent().find(".selected").removeClass("selected"); $(e).addClass("selected"); } } //Get search criteria function toMore(e) { $(e).parent().parent().find(".num").toggleClass("none"); $(e).toggleClass("more"); if (!$(e).hasClass("more")) { $(e).html("Retract>>"); } else { $(e).html("More>>"); } } function getDataList() { var data = {}; data.page = page; data.dbName = $('#dbName option:selected').val(); data.conditionVal = $('#condition').val(); data.condition = $('.divselect1 span').html(); data.sport = $('.sport .selected').attr("id"); data.country = $('.country .selected').attr("id"); data.time = $('.time .selected').html(); data.category = $('.category .selected').attr("id"); return data; } //Filtered search function toSelect() { $(".select_tkBox").hide(); } $("#dbName").change(function() { select(); }); //Search button function select() { //Delete filter content from last cache sessionStorage.removeItem('selectData'); var data = {}; data=getDataList() data.page = 0; page = 0; isreload = true; getData(data); } function getData(data) { $(".bottom-tip").css("display:none"); $.ajax({ type : "POST", url : "/searchList/getSearchList", data : JSON.stringify(data), contentType : "application/json;charset=UTF-8", dataType : "json", success : function(result) { $(".select_tkBox").hide(); if (result.data.length < 0) { $(".listul").html(""); $(".bottom-tip").css("display", "block"); isreload = false; } else { if (result.data.length < 10) { $(".bottom-tip").css("display", "block"); isreload = false; } $(".listul").html(template("view_searchList", result)); } scroll.refresh(); scroll.scrollTo(0, 0); //A new access, to clean up all related cache sessionStorage.removeItem("cacheKey"); sessionStorage.removeItem("articleId"); //Add a new access data addToCache("cacheKey",result.data); //Add a new filter sessionStorage.setItem('selectData',JSON.stringify(data)); } }); } function initData() { var data = {}; data.sport = '${sport!}'; data.category = '${category!}'; data.time = ''; data.country = ''; var articleId = sessionStorage.getItem("articleId"); var cacheData = sessionStorage.getItem("cacheKey"); if(articleId != null && cacheData != null){ var selectData = sessionStorage.getItem('selectData'); var sd = JSON.parse(selectData) if(sd.sport!=null&&sd.sport!=""){ data.sport = sd.sport; } if(sd.country!=null&&sd.country!=""){ data.country =sd.country; } if(sd.time!=null&&sd.time!=""){ data.time = sd.time; } if(sd.category!=null&&sd.category!=""){ data.category = sd.category; } } $.ajax({ type : "POST", url : "/searchList/initData", data : JSON.stringify(data), contentType : "application/json;charset=UTF-8", dataType : "json", success : function(result) { //project $(".sport").html(template("view_ydxm", result)); //Country $(".country").html(template("view_guojia", result)); //time $(".time").html(template("view_time", result)); //Information category $(".category").html(template("view_xxlb", result)); } }); } /* * @ touchend:Sliding end state * @ maxScrollY:Maximum scrolling height of screen */ // Slip end scroll.on('touchend',function(position) { if (isreload && position.y < (this.maxScrollY - 30)) { page++; // Add data to list var data = getDataList(); $.ajax({ type : "POST", url : "/searchList/getSearchList", data : JSON.stringify(data), contentType : "application/json;charset=UTF-8", dataType : "json", success : function(result) { if (result.data.length < 1) { //No data prompt isreload = false; $(".bottom-tip").css("display","block"); } else { for (var i = 0; i < result.data.length; i++) { var data = result.data; var template = ''; if (data[i].tablename == 'VIDEOINFO_METADATA') { template = '<li><div class="fl pxzbWord"><h2><a id="'+data[i].sys_fld_sysid+'" onclick="openUrl(\''+data[i].url+'\',\''+data[i].sys_fld_sysid+'\')">' + data[i].Title+ '</a></h2>'+ '<div class="pxzbWordRe"><span>' + data[i].Release date+ '</span><span>'+ data[i].author + '</span></div></div>'+ '<div class="fr pxzbPic">'; if (data[i].tflag == "0") { template = template+ '<img src="'+data[i].filePath+'"/>'; } else if (data[i].tflag == "1") { template = template+ '<img src="/review/getFile?fileName=' + data[i].fileName+ '&filePath='+ data[i].filePath+ '"/>'; } template = template+ '</div></li>'; } else { template = '<li><div class="fl pxzbWord pxzbWord100"><h2><a id="'+data[i].sys_fld_sysid+'" onclick="openUrl(\''+data[i].url+'\',\''+data[i].sys_fld_sysid+'\')">' + data[i].Title + '</a></h2>'+ '<div class="zhaiyao" >'+ data[i].abstract + '</div><div class="pxzbWordRe pxzbWord100Re"><span>' + data[i].Release date + '</span><span class="auther">' + data[i].author + '</span></div></div></li>' } // Add content to ul container var listContent = document.querySelector(".listul"); listContent.innerHTML = listContent.innerHTML+ template; } // Recalculate the height of the scrolling area after loading more scroll.refresh(); addToCache("cacheKey",result.data); } } }); } }); function goToIndex() { window.location.href = "index/mcIndex"; } //cacheKey cache key cachevalue cache content json structure function addToCache(cacheKey,cacheValue){ cacheValue = JSON.stringify(cacheValue); var allCacheData = sessionStorage.getItem(cacheKey); if(allCacheData != null){ allCacheData = allCacheData.substr(0, allCacheData.length - 1)+","+cacheValue.substr(1, cacheValue.length); } else { allCacheData = cacheValue; } sessionStorage.setItem(cacheKey,allCacheData); } function openUrl(url,id){ sessionStorage.setItem("articleId",id); window.location=url; } </script> </html>
4, Derivative issues:
1. Differences between sessionStorage and localStorage:
The sessionStorage property allows you to access a session Storage object. It is similar to localStorage, except that the data stored in localStorage has no expiration time setting, and the data stored in sessionStorage will be cleared at the end of the page session. The page session is maintained while the browser is open, and the original page session is maintained when the page is reloaded or restored.
The feature of sessionStorage is that when users open a tab, they actually establish a session session. In this tab, the url jumps, sessionStorage is actually saved, and it will not disappear. When the tab is closed, the data will disappear.