// pv--监听 url变动 import { innertEvent, on } from './utils' class Pv { private path: string private currentPageUrl: string constructor() { this.path = this.getPath(); this.currentPageUrl = document.referrer; this.recordPv(); this.sendPv(); } sendPv() { innertEvent.trigger('pv', { referrer: this.currentPageUrl }); this.currentPageUrl = location.href; } recordPv() { if(!history.pushState || !window.addEventListener) return; // hash监听 window.addEventListener('hashchange', () => { this.handleHashState(); }); // history监听 on(history, 'pushState', () => { this.pushStateOverride(); } ); on(history, 'replaceState', () => { this.replaceStateOverride(); } ); // history.pushState()或history.replaceState()不会触发popstate事件,需要监听 window.addEventListener('popstate', () => { this.handlePopState(); }); } // hash变动 handleHashState() { this.handleUrlChange(false); } // history变动 pushStateOverride() { this.handleUrlChange(true); } replaceStateOverride() { this.handleUrlChange(true); } handlePopState() { this.handleUrlChange(true); } getPath(): string { return location.pathname + location.search; } shouldTrackUrlChange(newPath: string, oldPath: string): boolean { return !!(newPath && oldPath); } // url变动 handleUrlChange(historyDidUpdate: boolean) { setTimeout(() => { // history变动 if (historyDidUpdate) { const oldPath = this.path; const newPath = this.getPath(); if(oldPath != newPath && this.shouldTrackUrlChange(newPath, oldPath)) { this.path = newPath; this.sendPv(); } } else { // 否则是hash变动 this.sendPv(); } }, 0); } } export default Pv