最近发现安卓系统在微信浏览器和webview里不支持window.location.reload() 和 window.location.href
场景:
//无效代码
let old_url = wwwe.baidu.com?lang=en; // 当前url
let new_url = www.baidu.com?lang=zh; // 目标url
window.location.href = new_url;
window.location.reload()
解决:
发现虽然 href 被设为 new_url,但是reload()一直无法执行。网上的方法是在url后加一串时间参数。即将例子中的第三行改写成
window.location.href = new_url + '?time='+((new Date()).getTime());
这个方法可以成功解决安卓在微信里无法reload的问题。安卓手机对微信浏览器进行缓存是根据根路由http://baidu.com/a/b的形式来缓存的,即如果微信浏览器缓存过www.baidu.com?lang=en 和 www.baidu.com?lang=zh后,reload默认是从缓存中装载文档,而不会刷新重新渲染整个页面。所以这个时候加时间戳就可以避免被浏览器判断为之前缓存过的页面。
封装了一个方法,如果url已经有时间戳,就只更新时间戳,否则则加上time参数(参数名可以自定义)
function refreshUrl(url,param){
let key= (param || 'time') +'='; //默认是"time"
let reg=new RegExp(key+'\\d+'); //正则:time=1472286066028
let timestamp=+new Date();
if(url.indexOf(key)>-1){ //有时间戳,直接更新
console.log('(reg,key+timestamp)',url.replace(reg,key+timestamp));
return url.replace(reg,key+timestamp);
}else{ //没有时间戳,加上时间戳
if(url.indexOf('?lang')>-1){
let urlArr=url.split('?lang=');
if(urlArr[1]){
return urlArr[0]+'?lang='+urlArr[1]+'&'+key+timestamp;
}else{
return urlArr[0]+'?'+key+timestamp;
}
}else{
return url+'?'+key+timestamp;
}
}
}
又一天坑解决:
后来在app里调用webview,发现webview里上述方法reload页面无效。网上查了一遍发现没有说这个问题的。固推测webview的缓存原则是判断 ? 参数前的路由路径,所以导致无法刷新。对于开头的例子,去掉?后的参数,那么url就都是www.baidu.com,所以webview会判断为同一路径,不会reload。
暴力解决: 博主用的react hash路由,固直接在hash前加时间戳就可以解决
const { href } = window.location;
const router = href.split('#/')[1];
const newUrl = `/?lang=${index}#/${router}`
补充:
一段网上很多博文里的reload、href科普,虽然解决这个问题的时候感觉没有用到这个知识点,但是也是新的知识。mark一下:
href是location对象的一个属性,reload()则是location对象的方法。所以对于href,可以为该属性设置新的 URL,使浏览器读取并显示新的 URL 的内容。
对于reload()则是重新加载当前文档,如果该方法没有规定参数,或者参数是 false,它就会用 HTTP 头 If-Modified-Since 来检测服务器上的文档是否已改变。如果文档已改变,reload() 会再次下载该文档。如果文档未改变,则该方法将从缓存中装载文档。这与用户单击浏览器的刷新按钮的效果是完全一样的。如果把该方法的参数设置为 true,那么无论文档的最后修改日期是什么,它都会绕过缓存,从服务器上重新下载该文档。这与用户在单击浏览器的刷新按钮时按住 Shift 健的效果是完全一样。