利用浏览器的window.performance.navigation.type属性(已经废弃)
| value | name | meaning |
|---|---|---|
| 0 | TYPE_NAVIGATE | The page was accessed by following a link, a bookmark, a form submission, a script, or typing the URL in the address bar. |
| 1 | TYPE_RELOAD | The page was accessed by clicking the Reload button or via the Location.reload() method. |
| 2 | TYPE_BACK_FORWARD | The page was accessed by navigating into the history |
| 3 | TYPE_RESERVED | Any other way. |
PerformanceNavigation
| value | name | meaning |
|---|---|---|
| 0 | TYPE_NAVIGATE | 当前页面是通过点击链接,书签和表单提交,或者脚本操作,或者在 url 中直接输入地址,type 值为 0 |
| 1 | TYPE_RELOAD | 点击刷新页面按钮或者通过Location.reload()方法显示的页面,type 值为 1 |
| 2 | TYPE_BACK_FORWARD | 页面通过历史记录和前进后退访问时。type 值为 2 |
| 255 | TYPE_RESERVED | 任何其他方式,type 值为 255 |
ios手机上返回上一页时候经常不触发vue等组件的mounted,从缓存读取的页码
window.addEventListener('pageshow', (e) => {
if (e.persisted) { // 从缓存中读取
// do somthing
}
)
综合上面完整的代码,完美方案如下
兼容navigation的新旧判断,以及ios返回上一页不触发mounted只触发pageshow的判断
mounted() {
if (isMobile && isIOS) {
window.addEventListener('pageshow', this.onPageShow)
} else if (isNavigationBackOrForward()) {
$emit('navigation-back-forward')
}
}
onPageShow(e: PageTransitionEvent) {
// 从缓存中打开
if (e.persisted) {
if (isNavigationBackOrForward()) {
$emit('navigation-back-forward')
}
}
}
isNavigationBackOrForward() {
if (!window.performance) {
return false
}
if (window.performance.navigation?.type === 2) {
return true
}
const entries = window.performance.getEntriesByType?.('navigation')
if (!entries || !entries.length) {
return false
}
return entries.find((entry: PerformanceEntry & { type?: string }) => entry.type === 'back_forward') || false
}
滚动到页面顶部
直接全部重写
router.scrollBehavior.js
mounted() {
// 不直接beforeMount中设置scrollTop,是因为web会先记住上次的位置再滚动
window.addEventListener('beforeunload', this.handleScrollTop)
}
beforeDestroy() {
window.removeEventListener('pageshow', this.handleScrollTop)
}
handleScrollTop() {
// 参考 https://www.zhangxinxu.com/wordpress/2022/05/history-scrollrestoration/
window.history.scrollRestoration = 'manual'
}
router.scrollBehavior.js文件如下
import { getMatchedComponents } from './utils'
if (process.client) {
if ('scrollRestoration' in window.history) {
window.history.scrollRestoration = 'manual'
// reset scrollRestoration to auto when leaving page, allowing page reload
// and back-navigation from other pages to use the browser to restore the
// scrolling position.
window.addEventListener('beforeunload', () => {
debugger
window.history.scrollRestoration = 'auto'
})
// Setting scrollRestoration to manual again when returning to this page.
window.addEventListener('load', () => {
debugger
window.history.scrollRestoration = 'manual'
})
}
}
export default function (to, from, savedPosition) {
// if the returned position is falsy or an empty object,
// will retain current scroll position.
let position = false
// if no children detected and scrollToTop is not explicitly disabled
const Pages = getMatchedComponents(to)
if (
Pages.length < 2 &&
Pages.every(Page => Page.options.scrollToTop !== false)
) {
// scroll to the top of the page
position = { x: 0, y: 0 }
} else if (Pages.some(Page => Page.options.scrollToTop)) {
// if one of the children has scrollToTop option set to true
position = { x: 0, y: 0 }
}
// savedPosition is only available for popstate navigations (back button)
if (savedPosition) {
position = savedPosition
}
// triggerScroll is only fired when a new component is loaded
if (to.path === from.path && to.hash !== from.hash) {
nuxt.$nextTick(() => nuxt.$emit('triggerScroll'))
}
return new Promise((resolve) => {
// wait for the out transition to complete (if necessary)
nuxt.$once('triggerScroll', () => {
// coords will be used if no selector is provided,
// or if the selector didn't match any element.
if (to.hash) {
let hash = to.hash
// CSS.escape() is not supported with IE and Edge.
if (typeof window.CSS !== 'undefined' && typeof window.CSS.escape !== 'undefined') {
hash = '#' + window.CSS.escape(hash.substr(1))
}
try {
if (document.querySelector(hash)) {
// scroll to anchor by returning the selector
position = { selector: hash }
}
} catch (e) {
console.warn('Failed to save scroll position. Please add CSS.escape() polyfill (https://github.com/mathiasbynens/CSS.escape).')
}
}
resolve(position)
})
})
}