history是一个用来管理历史会话的一个JS包。对于不同环境history提供了统一的API,用于用来管理历史堆栈(history stack)、导航,导航确认、持久化状态。

这段话翻译过来可能比较难懂,可以对比浏览器端原生的history对象来理解它的功能。对于浏览器端,其实就是对原生history对象进行再封装。

Installation

$ npm install --save history

如果使用了类似webpack的打包工具,通过如下示例使用:

// using ES6 modules
import createHistory from 'history/createBrowserHistory'

// using CommonJS modules
var createHistory = require('history').createBrowserHistory

或者直接引入,通过window.History引用:
<script src="https://unpkg.com/history/umd/history.min.js"></script>

Usage

根据不同环境,history包提供了三种创建history对象的方法:

可以通过使用import(或require)在包目录下引用(i.e.history/createBrowserHistory)。

以下文档使用createHistory术语代表以上三个方法的实现。

基础用法示例:

import createHistory from 'history/createBrowserHistory'

const history = createHistory()

// Get the current location.
const location = history.location

// Listen for changes to the current location.
const unlisten = history.listen((location, action) => {
  // location is an object like window.location
  console.log(action, location.pathname, location.state)
})

// Use push, replace, and go to navigate around.
history.push('/home', { some: 'state' })

// To stop listening, call the function returned from listen().
unlisten()

以下代码展示了每个create方法的参数以及对应的默认值,具体每个参数的作用后面详细介绍。

createBrowserHistory({
  basename: "", // The base URL of the app (see below)
  forceRefresh: false, // Set true to force full page refreshes
  keyLength: 6, // The length of location.key
  // A function to use to confirm navigation with the user (see below)
  getUserConfirmation: (message, callback) => callback(window.confirm(message))
})

createMemoryHistory({
  initialEntries: ["/"], // The initial URLs in the history stack
  initialIndex: 0, // The starting index in the history stack
  keyLength: 6, // The length of location.key
  // A function to use to confirm navigation with the user. Required
  // if you return string prompts from transition hooks (see below)
  getUserConfirmation: null
})

createHashHistory({
  basename: "", // The base URL of the app (see below)
  hashType: "slash", // The hash type to use (see below)
  // A function to use to confirm navigation with the user (see below)
  getUserConfirmation: (message, callback) => callback(window.confirm(message))
})

Properties

每种history对象都具有如下属性:

除此之外,createMemoryHistory还提供了history.indexhistory.entries属性,可以同来审查history stack.

Listening

通过history.listen监听当前地址变化。

history.listen((location, action) => {
  console.log(
    `The current URL is ${location.pathname}${location.search}${location.hash}`
  )
  console.log(`The last navigation action was ${action}`)
})

location对象实现了window.location接口的子集,包括:

并且还具有如下属性:

actionPUSHREPLACEPOP其中之一,取决于用户如何访问的当前URL。

可以通过如下方法,以编程的方式改变当前地址:

当使用pushreplace时,支持两种参数形式:

  1. 传入必需的path参数和可选的state参数。
  2. 传入一个类location对象: { pathname , search , hash , state }
// Push a new entry onto the history stack.
history.push("/home")

// Push a new entry onto the history stack with a query string
// and some state. Location state does not appear in the URL.
history.push("/home?the=query", { some: "state" })

// If you prefer, use a single location-like object to specify both
// the URL and state. This is equivalent to the example above.
history.push({
  pathname: "/home",
  search: "?the=query",
  state: { some: "state" }
})

// Go back to the previous history entry. The following
// two lines are synonymous.
history.go(-1)
history.goBack()

注意: 仅 createBrowserHistorycreateMemoryHistory 支持location state。

Blocking Transitions

history支持注册一个提示信息,会在通知history.listen()回调之前进行展示。
从而可以实现在用户离开当前页面之前提示用户是否要离开。

// Register a simple prompt message that will be shown the
// user before they navigate away from the current page.
const unblock = history.block("Are you sure you want to leave this page?")

// Or use a function that returns the message when it's needed.
history.block((location, action) => {
  // The location and action arguments indicate the location
  // we're transitioning to and how we're getting there.

  // A common use case is to prevent the user from leaving the
  // page if there's a form they haven't submitted yet.
  if (input.value !== "") return "Are you sure you want to leave this page?"
})

// To stop blocking transitions, call the function returned from block().
unblock()

注意: 在createMemoryHistory中使用此功能需要提供getUserConfirmation函数。(见下文)

Customizing the Confirm Dialog

默认情况下,使用window.confirm向用户展示提示信息。在创建history对象时提供getUserConfirmation函数,可以覆盖该默认行为。(或者使用createMemoryHistory时,该方法会假定不存在DOM环境)。

const history = createHistory({
  getUserConfirmation(message, callback) {
    // Show some custom dialog to the user and call
    // callback(true) to continue the transiton, or
    // callback(false) to abort it.
  }
})

Using a Base URL

如果在应用中所有URL都相对于一个"基本"URL,则可以使用basename参数。

const history = createHistory({
  basename: "/the/base"
})

history.listen(location => {
  console.log(location.pathname) // /home
})

history.push("/home") // URL is now /the/base/home

注意: createMemoryHistory 不支持 basename

Forcing Full Page Refreshes in createBrowserHistory

默认情况下,createBrowserHistory使用HTML的pushStatereplaceState来防止在导航时刷新整个页面。如果想要在URL变化时,重新加载页面,可以使用forceRefresh参数。

const history = createBrowserHistory({
  forceRefresh: true
})

Modifying the Hash Type in createHashHistory

默认情况下,createHashHistory"#/"的形式展示路径。可以通过hashType参数更改。

const history = createHashHistory({
  hashType: "slash" // the default
})

history.push("/home") // window.location.hash is #/home

const history = createHashHistory({
  hashType: "noslash" // Omit the leading slash
})

history.push("/home") // window.location.hash is #home

const history = createHashHistory({
  hashType: "hashbang" // Google's legacy AJAX URL format
})

history.push("/home") // window.location.hash is #!/home

About

history is developed and maintained by React Training. If
you're interested in learning more about what React can do for your company, please
get in touch!