history库的使用说明

2,406 阅读11分钟

image.png

安装:

这里history管理库发布在npm。您可以这样进行安装:

npm install --save history

引入:

通过Bundler:

使用history库最好的方式使用支持javascript模块化的打包器(我们建议使用Rollup)。最新版本的webpack以及Parcel也是不错的选择。

然后你就可以使用import语句来编写你的代码,像这样:

import { createBrowserHistory } from 'history';
// ...

如果你使用的打包器不理解JavaScript模块并且只理解CommonJS,您可以通过require引入:

var createBrowserHistory = require('history').createBrowserHistory;

通过标签:

如果您想通过标签加载这个库,您可以从unpkg中加载它。如果使用的浏览器支持javascript模块,仅需要使用history.development.js:

<script type="module">
// 在开发环境中使用 history.development.js
import { createBrowserHistory } from 'https://unpkg.com/history/history.production.min.js';
// ...
</script>

在尚不支持javascript模块的浏览器中,您也可以使用我们提供的UMD模块:

您可以在window.HistoryLibrary中找到该库

从这里开始:

简介:

这个库为运行在浏览器端以及有状态的环境端的javascript应用程序提供了history追踪以及导航原语。

如果你还没有,请花一点时间通读上面的安装指南,以便在您的系统中安装并运行该库。

我们提供了三种不同处理history的方法,具体取决于您依赖的环境:

  • browser history:适用于支持HTML5 history api的现代浏览器
  • hash history:适用于Web浏览器中,您希望将位置存储在当前URL的哈希部分中,以避免页面重新加载时将其发送到服务器。
  • memory history:被用于参考实现,可用于非浏览器环境,如React-Native或者测试。

主包为每个环境导出一个方法:createBrowserHistory用于浏览器环境,createHashHistory用于在浏览器中使用hash这种history形式的场景,createMemoryHistory用于创建内存history这种场景。

除了主包,该库也提供"history/browser"以及"history/hash"这两个包,它们可以导出单例,您可以使用它来快速获得一个在当前文档的history实例(web页面)

基本用法:

基本用法如下所示:

// 创建一个属于你的history实例
import { createBrowserHistory } from 'history';
let history = createBrowserHistory();

// 或者只导入browser history的单例
import history from 'history/browser';

// Alternatively, if you're using hash history import
// the hash history singleton instance.
// import history from 'history/hash';
// 作为选择,如果你使用hash/history导入hash history单例。可以这样import history from 'history/hash';

// 获得当前的location
let location = history.location;

// 监听当前location的变化
let unlisten = history.listen(({ location, action }) => {
  console.log(action, location.pathname, location.state);
});

// 使用push推送一条新entry到history栈中
history.push('/home', { some: 'state' });

// 使用replace去替换history栈中的当前entry
history.replace('/logged-in');

// Use back/forward to navigate one entry back or forward.
// 使用back/forward来向后或向前导航一个条目
history.back();

// 停止监听,调用从listen返回的函数
unlisten();

如果您会用memory history,您需要在您使用前创建您自己的history对象:

import { createMemoryHistory } from 'history';
let history = createMemoryHistory();

如果您在与当前document不同的window(例如iframe)使用browser或者hash的history,您需要创建您自己的browser/hash history。

import { createBrowserHistory } from 'history';
let history = createBrowserHistory({
  window: iframe.contentWindow
});

属性:

每一个history对象都有如下属性:

  • history.location:当前的location(详情如下)
  • history.action:当前当行的动作类型(详情如下)

此外,memory history提供history.index来告诉你在history栈中当前index。

监听:

您可以使用history.listen来监听当前location的改变:

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

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

  • location.pathname:URL地址
  • location.search:URL查询字符串
  • location.hash:URL的hash片段
  • location.state:location中的不能存在于URL中的一些额外状态
  • location.key:代表此location的唯一字符串

Action取值是Action.Push、Action.Replace、Action.Pop,具体取决于用于跳转到当前位置的方式

  • Action.Push:意思是将一个或多个条目添加到history栈中。
  • Action.Replace:意思是在history栈中的当前条目被替换。
  • Action.Pop:意思是在我们跳到了history堆栈中的其他位置。

清理:

当您使用history.listen添加了个监听器,它会返回一个用于移除监听器的函数,可以在清理逻辑中调用该函数。

let unlisten = history.listen(myListener);

// 当你完成之后
unlisten();

工具:

主包中也包含createPath以及parsePath这两个方法,这些方法在使用URL时可能会很拥有。

let pathPieces = parsePath('/the/path?the=query#the-hash');
// pathPieces = {
//   pathname: '/the/path',
//   search: '?the=query',
//   hash: '#the-hash'
// }

let path = createPath(pathPieces);
// path = '/the/path?the=query#the-hash

导航:

history对象可能被用于通过编程的方式改变当前location,具体方法如下:

  • history.push(to:To,state?:State)
  • history.replace(to:To,state?:State)
  • history.go(delta:nubmer)
  • history.back()
  • history.forward()
// 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 location-like object to specify the URL.
// This is equivalent to the example above.
history.push({
  pathname: '/home',
  search: '?the=query'
}, {
  some: state
});

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

阻塞过渡:

history允许您使用history.block(blocker:Blocker)API阻塞导航离开当前页面。例如:

// 阻塞导航并且注册一个回调,该回调当导航被阻塞时触发
let unblock = history.block(tx => {
  // 导航被阻塞!让我们展示一个确认框,这样用户就可以确认他们是否真的想要导航离开并且放弃他们当前页面做的更改。
  let url = tx.location.pathname;
  if (window.confirm(`Are you sure you want to go to ${url}?`)) {
    // 解除对导航的阻塞
    unblock();

    // 重新尝试跳转
    tx.retry();
  }
});

此示例使用的是window.confirm,如果您愿意,也可以使用自己自定义的确认框。

history.block将为所有页面内导航尝试调用您的回调,但对于重新加载页面的导航(例如刷新按钮或不使用history.push的链接),它会注册一个beforeunload处理程序以阻止导航。在现代浏览器中,您无法自定义此对话框。相反,你会看到类似的内容(chrome):

image.png

History Api参考

这是一个针对history的javascript库的api参考。

这个history库提供了一个通过包含URL以及STATE的location来追踪应用history的api。此参考包含库中接口的类型签名与返回值的描述。如果您还在寻找如何使用该库完成特定任务,请移步"从这里开始"。

概述:

环境:

    该history库支持三种不同的环境,或者模式选项。

  • browserHistory适合用于webapp场景。
  • hashHistory适合用于由于某种原因您不想或不能发送URL给服务端的webapp场景。
  • memoryHistory适合用于原生APP或者测试场景。

    只需为目标环境选择正确的模式,您就可以愉快的继续了。

监听:

    想要读取当前location和action,通过history.location和history.action。这两个属性当location发生变化时会自动改变。

    想要当location变化时被通知,使用history.listen装载一个监听器。

导航:

    想要改变location,您需要使用下面的之一:

  • history.push: push一个新的location到history栈。
  • history.replace:将当前location替换为其他location。
  • history.go:通过给定的值更改history堆栈中的当前索引。
  • history.back:在history堆栈中导航回退一个条目。
  • history.forward:在history堆栈中导航向前一个条目。

确认导航:

    想要阻止location变更,请使用history.block。该API允许您有机会阻止location变更,您可以在重试过渡之前提示用户。

创建链接:

    如果您构建一个链接,您需要使用history.createHref来获取可用作值的URL。

参考:

    该库的源码是通过TypeScript写的,但是它在发布之前被编译为javascript。在参考中的一些方法签名中包含它们的TypeScript类型的注释,但是您也可以随时参考原始来源。

Action:

    Action表示历史history堆栈中发生的一种更改。Action有三种枚举:

  • Action.Pop:对history堆栈中任意索引的更改,例如向后或向前的导航。这不描述导航的方向,只描述索引发生了变化。这是新创建history对象的默认操作。
  • Action.Push:标示一个新添加的条目被添加到history堆栈中,例如当链接被点击或者新页面被加载。当这种情况发生时,堆栈中所有后续条目将会丢失。
  • Action.Replace:指示history堆栈中当前索引处的条目被新条目替换。

更多详情请查看"从这里开始"

createBrowserHistory:

declare createBrowserHistory({ window?: Window }): BrowserHistory;

interface BrowserHistory<S extends State = State> {
  readonly action: Action;
  readonly location: Location<S>;
  createHref(to: To): string;
  push(to: To, state?: S): void;
  replace(to: To, state?: S): void;
  go(n: number): void;
  back(): void;
  forward(): void;
  listen(listener: Listener<S>): () => void;
  block(blocker: Blocker<S>): () => void;
}

浏览器历史对象使用浏览器的内置history堆栈跟踪应用程序的浏览历史。它被设计运行在支持包含pushState、replaceState、popState事件的HTML5-history接口的现代浏览器。

createBrowserHistory返回一个BrowserHistory实例。window 默认为当前文档的 defaultView。

import { createBrowserHistory } from 'history';
let history = createBrowserHistory();

详情请查看”从这里开始“

createPath和parsePath

declare createPath(partialPath: PartialPath): string;
declare parsePath(path: string): PartialPath;

interface PartialPath {
  pathname?: string;
  search?: string;
  hash?: string;
}

createPath和parsePath被用于创建和解析URL地址。

createPath({ pathname: '/login', search: '?next=home' }); // "/login?next=home"
parsePath('/login?next=home'); // { pathname: '/login', search: '?next=home' }

createHashHistory

declare createHashHistory({ window?: Window }): HashHistory;

interface HashHistory<S extends State = State> {
  readonly action: Action;
  readonly location: Location<S>;
  createHref(to: To): string;
  push(to: To, state?: S): void;
  replace(to: To, state?: S): void;
  go(n: number): void;
  back(): void;
  forward(): void;
  listen(listener: Listener<S>): () => void;
  block(blocker: Blocker<S>): () => void;
}

hash history对象使用浏览器内置history堆栈。它被设计运行在支持包含pushState、replaceState、popState事件的HTML5-history接口的现代浏览器。

createHashHistory返回一个HashHistory实例。window 默认为当前文档的 defaultView。

不同于BrowserHistory的区别在于HashHistory会将当前位置存储在URL的哈希部分中,这意味着它永远不会发送到服务器。如果您将站点托管在无法完全控制服务器路由的域上,或者例如在您不想配置“服务器”以在不同 URL 上提供相同页面的 Electron 应用程序中。

import { createHashHistory } from 'history';
let history = createHashHistory();

详情请查看”从这里开始“

createMemoryHistory

declare createMemoryHistory({
  initialEntries?: InitialEntry[],
  initialIndex?: number
}): MemoryHistory;

type InitialEntry = string | PartialLocation;

interface MemoryHistory<S extends State = State> {
  readonly index: number;
  readonly action: Action;
  readonly location: Location<S>;
  createHref(to: To): string;
  push(to: To, state?: S): void;
  replace(to: To, state?: S): void;
  go(n: number): void;
  back(): void;
  forward(): void;
  listen(listener: Listener<S>): () => void;
  block(blocker: Blocker<S>): () => void;
}

MemoryHistory通过一个内部数组来追踪应用的浏览记录。这使它非常适合完全控制history堆栈的场景,例如:ReactNative和测试。

createMemoryHistory返回一个MemoryHistory实例。您可以通过initialEntries属性向此history实例提供初始条目,该属性默认为['/'](根目录URL中的单个位置)。initialIndex默认为initialEntries中最后一个条目的索引。

import { createMemoryHistory } from 'history';
let history = createMemoryHistory();
// Or, to pre-seed the history instance with some URLs:
let history = createMemoryHistory({
  initialEntries: ['/home', '/profile', '/about']
});

更多详情请查看"从这里开始"

history.action

当前或者最近修改history堆栈的Action。这个属性会随着当前location的变化而变化。

详情请查看history.listen

history.back()

从history堆栈中回退一个条目。相当于history.go(-1)

更多详情请查看"从这里开始"

history.block(blocker:Blocker)

interface Blocker<S extends State = State> {
  (tx: Transition<S>): void;
}

interface Transition<S extends State = State> {
  action: Action;
  location: Location<S>;
  retry(): void;
}

阻止history堆栈发生变化。这个API在您想要阻止用户导航离开当前页面非常有用,例如当前页面有些未保存的数据。

// 开始阻止history堆栈变动
let unblock = history.block(({ action, location, retry }) => {
  // 过渡被阻止
});

// 而后,您想要继续进行过渡
unblock();

更多详情请查看"从这里开始"

history.createHref(to:To)

返回一个适合用作 值的字符串,该值将导航到给定的目的地。

history.forward()

在history堆栈中向前一个条目。相当于history.go(1)。

更多详情请查看"从这里开始"

history.go(delta:number)

在堆栈中向前或向后delta个条目。

更多详情请查看"从这里开始"

history.index

在history堆栈中的当前索引

[!Note:]

This property is available only on memory history instances.

history.location

当前location。这个属性会随着location的变动而变动。

详情请看"history.listen"

history.push(to:To,state?:State)

push一个新的条目到堆栈中

更多详情请查看"从这里开始"

history.replace(to:To,state?:State)

用一个新的条目替换堆栈中的当前条目

更多详情请查看"从这里开始"

Location

interface Location<S extends State = State> {
  pathname: string;
  search: string;
  hash: string;
  state: S;
  key: string;
}

location是历史堆栈中特定的条目,通常类似于应用程序中的”页面“或”屏幕“,当用户点击链接并在应用中移动,当前location便发生变化。

location.pathname

location.pathname是一个字符串,其中包含首字符”/“后跟URL的其余部分,直到"?"。

另请参见URL.pathname

location.search

location.search属性是一个字符串,其中包含首字符"?"后跟随key=value对的查询字符串。如果没有参数,这个值应该是空串('')。

location.hash

location.hash属性是一个字符串,其中包含首字符”#“后跟URL的唯一片段。如果没有这个唯一片段,这个值应该是个空值('')。

location.state

location.state属性是与此location关联的用户提供的State对象。这可能存储您不想放入URL的任何信息的有用位置,例如:特定于会话的数据。

[!Note:]

In web browsers, this state is managed using the browser's built-in pushState, replaceState, and popstate APIs. See also History.state.
location.key

location.key是与此location关联的唯一字符串。在初始位置,这将是字符串默认值。在所有后续位置,此字符串将是唯一标识符。

当您需要跟踪同一URL的2种不同状态时,这很有用。

State

type State = object | null;

状态值是与Location关联的但未出现在URL中的额外信息的对象。该值始终与location相关联。

更多详情请查看"从这里开始"

To

type To = string | PartialPath;

interface PartialPath {
  pathname?: string;
  search?: string;
  hash?: string;
}

To的值表示目标位置,但不包含普通location对象的所有信息。它主要被用于history.push以及history.replace的第一个参数。

更多详情请查看"从这里开始"

参考:

1. developer.mozilla.org/zh-CN/docs/… 【MDN-beforeunload】