JavaScript
URL

URLのハッシュやパラメータの変更を監視するライブラリを作った

はじめに

タブでコンテンツを切り替えるページを実装するとき,あなたならどう実装しますか?
方法はいろいろありますが,URLのハッシュ(http://www.example.com/index.html#hash#hashの部分)を利用する方法が考えられるかと思います。タブのリンク先をハッシュとして,変更された時にコンテンツを切り替える処理を走らせればいいわけです。でも変更を監視するのって結構めんどいですよね。

似たような話で,ページが開かれる時に指定されたURLパラメータ(URLに付いている?key1=hoge&key2=fugaみたいなやつ)によって処理を分岐させたいことがあると思います。例えば「このリンクからページに飛んだ時は最初にメッセージを表示する」とか。でもURLパラメータの取得って結構めんどい。

そんなわけで,ハッシュの変更を監視してイベントを発火し,ついでにパラメータも取得する簡易的なライブラリ 1 を作りました。

ソースはこちら
デモはこちら

何が出来るの?

URLのハッシュが変更されたら,イベントを発火します。

http://www.example.com/index.html#hogehttp://www.example.com/index.html#fuga

document.addEventListener("changeLocation", e => {
    console.log(e.location.hash); //#fuga
});

パラメータはオブジェクトにして返します。

http://www.example.com/index.html?key1=fuga&key2=piyo

document.addEventListener("changeLocation", e => {
    console.log(e.location.parameters); //{key1: "fuga", key2: "piyo"}
});

コード

ソースはこちら

MonitoringLocation.js
class MonitoringLocation {
    constructor(intervalMS = 100) {
        this.prevHref = location.href;
        this.intervalMS = intervalMS;
    }

    enable() {
        const self = this;
        this.timer = setInterval(() => {
            self.checkLocation()
        }, this.intervalMS);
    }

    disable() {
        clearInterval(this.timer);
    }

    checkLocation() {
        if (this.prevHref != location.href) this.fireEvent();
        this.prevHref = location.href;
    }

    fireEvent() {
        const event = document.createEvent('HTMLEvents');
        event.initEvent('changeLocation', true, false);
        event.location = location;
        event.location.parameters = this.getParams(location.search);

        document.dispatchEvent(event);
    }

    getParams(search) {
        let params = {};
        if (!search.split('?')[1]) return params;

        const keyValues = search.split('?')[1].split('&');
        for (let i of keyValues) {
            params[i.split('=')[0]] = i.split('=')[1];
        }
        return params;
    }
}

使い方

デモはこちら
こんな感じで使います

const eventHandler = e => {
    console.log(e.location.hash); //#fuga
    console.log("params:", e.location.parameters); //{key1: "fuga", key2: "piyo"}
}

document.addEventListener("changeLocation", eventHandler);

const monitoringLocation = new MonitoringLocation();
monitoringLocation.enable();
monitoringLocation.fireEvent();

クラス宣言

URLを監視するインターバル(ミリ秒)を引数として指定できます。なにも指定しなければ100ms。

const monitoringLocation = new MonitoringLocation();

もしくは

const monitoringLocation = new MonitoringLocation(10);

監視を有効にする

monitoringLocation.enable();

監視を無効にする

monitoringLocation.disable();

イベントを強制的に発火

ページを開いたタイミングでパラメータを取得したい場合などにはこれを使います。

monitoringLocation.fireEvent();

リスナ登録

イベントタイプを"changeLocation"としてリスナを登録します。
リスナの引数にはlocationが含まれます。
URLパラメータはオブジェクトとしてlocation.parametersに格納されています。

document.addEventListener("changeLocation", eventHandler);

function eventHandler(e){
    console.log(e.location.hash); //#fuga
    console.log("params:", e.location.parameters); //{key1: "fuga", key2: "piyo"}
}

注意点

URLにパラメータとハッシュが混在する時はパラメータを先,ハッシュを最後にしてください。

良い例

http://www.example.com/index.html?key1=hoge&key2=fuga#hash

ダメな例

http://www.example.com/index.html#hash?key1=hoge&key2=fuga

おわりに

もしよければ使ってみてください。
ソースはこちら
デモはこちら


  1. 規模が小さすぎるのでライブラリと言って良いのか分からない