12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- /* @flow */
- import type Router from '../index'
- import { History } from './base'
- import { cleanPath } from '../util/path'
- import { START } from '../util/route'
- import { setupScroll, handleScroll } from '../util/scroll'
- import { pushState, replaceState, supportsPushState } from '../util/push-state'
- export class HTML5History extends History {
- _startLocation: string
- constructor (router: Router, base: ?string) {
- super(router, base)
- this._startLocation = getLocation(this.base)
- }
- setupListeners () {
- if (this.listeners.length > 0) {
- return
- }
- const router = this.router
- const expectScroll = router.options.scrollBehavior
- const supportsScroll = supportsPushState && expectScroll
- if (supportsScroll) {
- this.listeners.push(setupScroll())
- }
- const handleRoutingEvent = () => {
- const current = this.current
- // Avoiding first `popstate` event dispatched in some browsers but first
- // history route not updated since async guard at the same time.
- const location = getLocation(this.base)
- if (this.current === START && location === this._startLocation) {
- return
- }
- this.transitionTo(location, route => {
- if (supportsScroll) {
- handleScroll(router, route, current, true)
- }
- })
- }
- window.addEventListener('popstate', handleRoutingEvent)
- this.listeners.push(() => {
- window.removeEventListener('popstate', handleRoutingEvent)
- })
- }
- go (n: number) {
- window.history.go(n)
- }
- push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
- const { current: fromRoute } = this
- this.transitionTo(location, route => {
- pushState(cleanPath(this.base + route.fullPath))
- handleScroll(this.router, route, fromRoute, false)
- onComplete && onComplete(route)
- }, onAbort)
- }
- replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
- const { current: fromRoute } = this
- this.transitionTo(location, route => {
- replaceState(cleanPath(this.base + route.fullPath))
- handleScroll(this.router, route, fromRoute, false)
- onComplete && onComplete(route)
- }, onAbort)
- }
- ensureURL (push?: boolean) {
- if (getLocation(this.base) !== this.current.fullPath) {
- const current = cleanPath(this.base + this.current.fullPath)
- push ? pushState(current) : replaceState(current)
- }
- }
- getCurrentLocation (): string {
- return getLocation(this.base)
- }
- }
- export function getLocation (base: string): string {
- let path = window.location.pathname
- if (base && path.toLowerCase().indexOf(base.toLowerCase()) === 0) {
- path = path.slice(base.length)
- }
- return (path || '/') + window.location.search + window.location.hash
- }
|