SPA Navigate Library

History APIフックによるSPAページ遷移検知ライブラリ。SPANavigate.on() でコールバックを登録する。

Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta // @require https://update.greasyfork.org/scripts/570420/1779088/SPA%20Navigate%20Library.js

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(Tôi đã có Trình quản lý tập lệnh người dùng, hãy cài đặt nó!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         SPA Navigate Library
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  History APIフックによるSPAページ遷移検知ライブラリ。SPANavigate.on() でコールバックを登録する。
// @author       ...
// @match        *://*/*
// @grant        none
// @license      MIT
// ==/UserScript==

/**
 * 使い方:
 *
 *   // @require で読み込んだ後、以下のように使う
 *
 *   SPANavigate.on(({ pathname, href }) => {
 *     console.log("遷移先:", pathname);
 *   });
 *
 *   // 登録解除
 *   const handler = ({ pathname }) => { ... };
 *   SPANavigate.on(handler);
 *   SPANavigate.off(handler);
 */

(function () {
  "use strict";

  if (window.SPANavigate) return; // 二重読み込み防止

  const _listeners = new Set();

  function _dispatch() {
    const info = { pathname: location.pathname, href: location.href };
    for (const fn of _listeners) {
      try { fn(info); } catch (e) { console.error("[SPANavigate]", e); }
    }
  }

  // pushState / replaceState をフック
  const _push = history.pushState.bind(history);
  const _replace = history.replaceState.bind(history);

  history.pushState = (...args) => { _push(...args); _dispatch(); };
  history.replaceState = (...args) => { _replace(...args); _dispatch(); };

  // ブラウザの戻る/進む
  window.addEventListener("popstate", _dispatch);

  // 初回ロード
  window.addEventListener("load", _dispatch);

  window.SPANavigate = {
    /** コールバックを登録。引数: { pathname, href } */
    on(fn) { _listeners.add(fn); },
    /** コールバックを解除 */
    off(fn) { _listeners.delete(fn); },
  };
})();