摘要:去查看一下的源碼,發(fā)現(xiàn)被改裝了,監(jiān)聽的回調(diào)回在事件觸發(fā)的時(shí)候觸發(fā)。搞清楚的觸發(fā)機(jī)制根據(jù)的描述當(dāng)活動(dòng)歷史記錄條目更改時(shí),將觸發(fā)事件。說明了上,依舊不能阻止的觸發(fā)。最終解決由于刷新重新加載是肯定不會(huì)觸發(fā)的,所以可以后進(jìn)行。
背景:
在使用Tarojs開發(fā)的時(shí)候,發(fā)現(xiàn)在ios上跳轉(zhuǎn)至其他頁(yè)面,再返回回來會(huì)出現(xiàn)接口接連調(diào)用兩次的情況。
排查過程:1.由于接口調(diào)用在組件的didMount里,所以看其他的組件也是didMount調(diào)用兩次,這讓我感覺很詫異,componentDidMount這個(gè)生命周期應(yīng)該不會(huì)調(diào)用兩次的;
2.我打開了weinre查看,發(fā)現(xiàn)了有兩個(gè)一模一樣的頁(yè)面組件,如下圖
因?yàn)槭莚outer層級(jí)上double了,所以所有組件都會(huì)實(shí)例化兩次,此時(shí)我懷疑是taro/router的問題。
我又去看了一下果園是否也是有同樣的情況,結(jié)果發(fā)現(xiàn)在page componentDidMount里調(diào)用的tree/get等首屏數(shù)據(jù)接口調(diào)用了兩次。。。
去查看一下@tarojs/router的源碼,發(fā)現(xiàn)
history被tarojs/router改裝了,history.listen監(jiān)聽的回調(diào)回在popstate事件觸發(fā)的時(shí)候觸發(fā)。
現(xiàn)在的問題根源確定了是由于popstate事件的觸發(fā),導(dǎo)致了tarojs/router認(rèn)為當(dāng)前頁(yè)面是進(jìn)行了一次前端路由跳轉(zhuǎn),所以進(jìn)行了兩次頁(yè)面級(jí)別的渲染,導(dǎo)致所有的組件實(shí)例的生命周期都走了兩次。那么問題來了,明明我們根本沒有利用history的特性,所有的跳轉(zhuǎn)都是刷新式跳轉(zhuǎn),為什么這個(gè)popstate會(huì)觸發(fā)呢。
3.搞清楚popstate的觸發(fā)機(jī)制
根據(jù)MDN的描述:
當(dāng)活動(dòng)歷史記錄條目更改時(shí),將觸發(fā)popstate事件。如果被激活的歷史記錄條目是通過對(duì)history.pushState()的調(diào)用創(chuàng)建的,或者受到對(duì)history.replaceState()的調(diào)用的影響,popstate事件的state屬性包含歷史條目的狀態(tài)對(duì)象的副本。
需要注意的是調(diào)用history.pushState()或history.replaceState()不會(huì)觸發(fā)popstate事件。只有在做出瀏覽器動(dòng)作時(shí),才會(huì)觸發(fā)該事件,如用戶點(diǎn)擊瀏覽器的回退按鈕(或者在Javascript代碼中調(diào)用history.back())
理論上popstate是不會(huì)在我們的應(yīng)用了觸發(fā)的,我試驗(yàn)了一下這個(gè)東西究竟是何方神圣。
var a = document.getElementById("a"); a.onclick = function() { location.href = "/aaa.html" } window.addEventListener(‘popstate’, function handlePopState() { console.log("handlePopState") }, false);
點(diǎn)擊后返回,壓根沒有觸發(fā)popstate,不管在ios還是android上。
然后我將
location.href = ‘/aaa.html"
替換成
history.replaceState(null, "", "aaa.html");
在ios上返回是無刷新式的返回,觸發(fā)了popstate事件,僅僅url回退成popstate.html。
在android上返回是刷新式返回,同樣觸發(fā)了popstate事件,然后會(huì)重新解析/加載/執(zhí)行。
到這里已經(jīng)確定了location.href的跳轉(zhuǎn)后返回是不會(huì)觸發(fā)popstate的,因?yàn)槭撬⑿率降姆祷?,那就是我們?cè)跇I(yè)務(wù)里有動(dòng)了history的api,此時(shí)我懷疑是在業(yè)務(wù)底層代碼使用了history。
4.查看業(yè)務(wù)底層跳轉(zhuǎn)代碼
看到navigation.forward在H5僅僅使用了location.href進(jìn)行跳轉(zhuǎn),但是在此之前為了加is_back參數(shù)表示當(dāng)前頁(yè)面是通過回退到達(dá)的,使用了history.replaceState。
我模擬一下這個(gè)操作
var a = document.getElementById("a"); a.onclick = function() { history.replaceState(null, "", "popstate33.html?a=1"); location.href = "/aaa.html" }
果不其然,在ios里在返回的時(shí)候會(huì)觸發(fā)popstate事件,而android不會(huì)觸發(fā)。
說明了ios上,依舊不能阻止popstate的觸發(fā)。
5.解決方案
由于在ios中返回頁(yè)面會(huì)觸發(fā)popstate,在tarojs/router此時(shí)認(rèn)為進(jìn)行了一次前端路由
5.1 在進(jìn)入頁(yè)面后根據(jù)is_back進(jìn)行一次reload
5.2 在底層跳轉(zhuǎn)代碼包上進(jìn)行再一次包裝,跳轉(zhuǎn)的時(shí)候不再使用history.replaceState
然而。。。。。。。tarojs/router有這么一行- -,也就是業(yè)務(wù)層不使用history.replaceState,它自己本身也用了,我把這行注釋掉,且業(yè)務(wù)上不使用replaceState,ios回退才不會(huì)觸發(fā)popstate。
所以。。。。
5.1由于不能使用replaceState將is_back去掉,不然將無限循環(huán)刷新;
5.2由于tarojs/router本身自己使用了history.replaceState,也沒有了意義。
一切又回到了起點(diǎn)。。。。
最終解決
由于刷新重新加載是肯定不會(huì)觸發(fā)popstate的,所以可以replaceState后進(jìn)行reload。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/106161.html
摘要:?jiǎn)雾?yè)應(yīng)用的原理從早起的根據(jù)的變化,到根據(jù)的的變化,實(shí)現(xiàn)無刷新條件下的頁(yè)面重新渲染。那么在單頁(yè)應(yīng)用中是如何監(jiān)聽的變化呢,本文將總結(jié)一下,如何在單頁(yè)頁(yè)面中優(yōu)雅的監(jiān)聽的變化。在下幾章中,重點(diǎn)介紹一下如何監(jiān)聽的改變。 ??單頁(yè)應(yīng)用的原理從早起的根據(jù)url的hash變化,到根據(jù)H5的history的變化,實(shí)現(xiàn)無刷新條件下的頁(yè)面重新渲染。那么在單頁(yè)應(yīng)用中是如何監(jiān)聽url的變化呢,本文將總結(jié)一下,...
摘要:?jiǎn)雾?yè)應(yīng)用的原理從早起的根據(jù)的變化,到根據(jù)的的變化,實(shí)現(xiàn)無刷新條件下的頁(yè)面重新渲染。那么在單頁(yè)應(yīng)用中是如何監(jiān)聽的變化呢,本文將總結(jié)一下,如何在單頁(yè)頁(yè)面中優(yōu)雅的監(jiān)聽的變化。在下幾章中,重點(diǎn)介紹一下如何監(jiān)聽的改變。 ??單頁(yè)應(yīng)用的原理從早起的根據(jù)url的hash變化,到根據(jù)H5的history的變化,實(shí)現(xiàn)無刷新條件下的頁(yè)面重新渲染。那么在單頁(yè)應(yīng)用中是如何監(jiān)聽url的變化呢,本文將總結(jié)一下,...
摘要:?jiǎn)雾?yè)應(yīng)用的原理從早起的根據(jù)的變化,到根據(jù)的的變化,實(shí)現(xiàn)無刷新條件下的頁(yè)面重新渲染。那么在單頁(yè)應(yīng)用中是如何監(jiān)聽的變化呢,本文將總結(jié)一下,如何在單頁(yè)頁(yè)面中優(yōu)雅的監(jiān)聽的變化。在下幾章中,重點(diǎn)介紹一下如何監(jiān)聽的改變。 ??單頁(yè)應(yīng)用的原理從早起的根據(jù)url的hash變化,到根據(jù)H5的history的變化,實(shí)現(xiàn)無刷新條件下的頁(yè)面重新渲染。那么在單頁(yè)應(yīng)用中是如何監(jiān)聽url的變化呢,本文將總結(jié)一下,...
摘要:與事件都是瀏覽器歷史記錄,兩者都是中的,相對(duì)而言比更為強(qiáng)大。事件本身只是監(jiān)測(cè)的變化,我認(rèn)為目前其主要意義就是與搭配使用從而使得在下歷史記錄前進(jìn)后退按鈕依然有效。地址新的歷史記錄條目的地址。 hashchange與popstate事件都是瀏覽器歷史記錄API,兩者都是HTML5中的API,相對(duì)而言popstate比hashchange更為強(qiáng)大。注意這兩種歷史記錄管理都受同源策略的限制,這...
摘要:?jiǎn)栴}最近碰到兩個(gè)問題從首頁(yè)進(jìn)入列表頁(yè)之后,點(diǎn)擊下一頁(yè)的時(shí)候,使用請(qǐng)求更新數(shù)據(jù),然后點(diǎn)擊瀏覽器后退按鈕就直接返回到首頁(yè),實(shí)際這里想要的效果是返回列表頁(yè)上一頁(yè)。沒法記住之前分頁(yè)狀態(tài)。 問題 最近碰到兩個(gè)問題: 從首頁(yè)進(jìn)入列表頁(yè)之后,點(diǎn)擊下一頁(yè)的時(shí)候,使用ajax請(qǐng)求更新數(shù)據(jù), 然后點(diǎn)擊瀏覽器后退按鈕就直接返回到首頁(yè),實(shí)際這里想要的效果是返回列表頁(yè)上一頁(yè)。 在列表頁(yè)分頁(yè)為2的頁(yè)面進(jìn)入詳情頁(yè),...
閱讀 4047·2021-09-24 10:24
閱讀 1407·2021-09-22 16:01
閱讀 2727·2021-09-06 15:02
閱讀 1028·2019-08-30 13:01
閱讀 1016·2019-08-30 10:52
閱讀 642·2019-08-29 16:36
閱讀 2245·2019-08-29 12:51
閱讀 2341·2019-08-28 18:29