BLOG

クラスについて(javascript)

おはようございます。

オンラインもくもく会ナウどうもハヤトワンです。

足湯しながら作業しとります。(癒やし)

ということで今日はjavascriptのクラスについて改めて勉強するので、ここにまとめようと思います。

クラスを使うメリット

・クラスの中の世界と外の世界で実装を切り離すことができる。

・なのでクラスのメソッドの使い方と引数の渡し方さえ覚えれば、クラスの内部で起こっていることはあまり関与する必要がない。(複数人で開発する際は特に)

・修正する場合もクラスを修正すれば、他のメソッドにも反映されるので修正が楽になる。

プライベートメソッドとパブリックメソッド

プライベートメソッドはアンダースコアからはじまる

意味はクラスの中だけでしか呼ばないでくれと他の開発者に明示している。

例:_splitText(){}

パブリックメソッドはアンダースコアなし

外から呼べる(厳密にはプライベートメソッドも外から呼べるが開発者間の暗黙の了解的な意味でプライベートメソッドと分類される)

例:animate(){}

実際にクラスを使ってみる

下記のようなコードだと複数個アニメーションを当てたいときにコードが冗長になる

 index.html

<body>
    <div id="container">
        <div class="animate-title">
            WHAT'S UP
        </div>
        <div class="animate-title-2">
            BROOOOOO
        </div>
        <button class="button" onclick="document.querySelector('.animate-title').classList.toggle('inview');">push-1</button>
        <button class="button" onclick="document.querySelector('.animate-title-2').classList.toggle('inview');">push-2</button>
    </div>
    <script src="main.js"></script>
</body>

main.js

document.addEventListener('DOMContentLoaded', function() {
    const el = document.querySelector('.animate-title');
    const el2 = document.querySelector('.animate-title-2');
    const str = el.innerHTML.trim().split("");
    const str2 = el2.innerHTML.trim().split("");

    el.innerHTML = str.reduce((acc, curr) => {
        curr = curr.replace(/\s+/, '&nbsp;');
        return `${acc}<span class="char">${curr}</span>`;
    }, "");
    el2.innerHTML = str2.reduce((acc, curr) => {
        curr = curr.replace(/\s+/, '&nbsp;');
        return `${acc}<span class="char">${curr}</span>`;
    }, "");
})

こういう場合にクラスを適応すると

クラスを適用後

index.html

<body>
    <div id="container">
        <div class="animate-title">
            WHAT'S UP
        </div>
        <div class="animate-title-2">
            BROOOOOO
        </div>
        <button class="button" onclick="document.querySelector('.animate-title').classList.toggle('inview');">push-1</button>
        <button class="button" onclick="document.querySelector('.animate-title-2').classList.toggle('inview');">push-2</button>
    </div>
    <script src="main.js"></script>
</body>

main.js

document.addEventListener('DOMContentLoaded', function() {
const ta = new TextAnimation('.animate-title');
const ta2 = new TextAnimation('.animate-title-2');
ta.animate();
ta2.animate();
});

class TextAnimation {
    constructor(el) {
        this.el = document.querySelector(el);
    this.chars = this.el.innerHTML.trim().split("");
    this.el.innerHTML = this._splitText();
    //このthisは変数taを指す
}
    _splitText() {
        return this.chars.reduce((acc, curr) => {
            curr = curr.replace(/\s+/, '&nbsp;');
            return `${acc}<span class="char">${curr}</span>`;
        },"");
    }
    animate() {
        this.el.classList.toggle('inview');
    }
}

基本はこの形でクラスを作って

class hogehoge {
    constructor() {

}

それをインスタンス化

const hoge = new hogehoge();

っていう流れ。

今回のクラス適用を解説すると、下記のような流れになる。

    const el = document.querySelector('.animate-title');

こいつをクラスの中にいれて、先頭にthisを加え、constructor,querySelectorの引数はelに変更し、クラス名はインスタンスにて渡す。

class TextAnimation {
    constructor(el) {
        this.el = document.querySelector(el);
}
const ta = new TextAnimation('.animate-title');

こうすることで.animate-title-2ができても下記のように増やせる

const ta = new TextAnimation('.animate-title');
const ta2 = new TextAnimation('.animate-title-2');

同じようにconst str を下記のようにクラスに加える

※変数名を変更してるのはstrだと文字列を意味し、charsは一文字ずつの配列ということを指す為

this.chars = this.el.innerHTML.trim().split("");

そして内部で使用する_splitText()を加え、その中にreduce処理を加え(こちらもcharsに置き換える)、constructor内にて、this.el.innerHTMLにthis._spiltText();を代入する。

class TextAnimation {
    constructor(el) {
        this.el = document.querySelector(el);
        this.chars = this.el.innerHTML.trim().split("");
        this.el.innerHTML = this._splitText();
    //このthisは変数taを指す
}
    _splitText() {
        return this.chars.reduce((acc, curr) => {
            curr = curr.replace(/\s+/, '&nbsp;');
            return `${acc}<span class="char">${curr}</span>`;
        },"");
    }
}

そして、初期化を行う

document.addEventListener('DOMContentLoaded', function() {
const ta = new TextAnimation('.animate-title');
const ta2 = new TextAnimation('.animate-title-2');
});

クラスをDOMcontentLoadedの中で呼んでいないのは、クラスが定義された段階ではまだ実行されていなく、特に問題ないから。

コードが動くのはnew演算子でインスタンス化を行ったときになる。

加えて、アニメーションはinviewがトリガーになっているので、

下記のようにできる。

document.addEventListener('DOMContentLoaded', function() {
const ta = new TextAnimation('.animate-title');
const ta2 = new TextAnimation('.animate-title-2');
ta.animate();
ta2.animate();
});

class TextAnimation {
    constructor(el) {
        this.el = document.querySelector(el);
        this.chars = this.el.innerHTML.trim().split("");
        this.el.innerHTML = this._splitText();
    //このthisは変数taを指す
}
    _splitText() {
        return this.chars.reduce((acc, curr) => {
            curr = curr.replace(/\s+/, '&nbsp;');
            return `${acc}<span class="char">${curr}</span>`;
        },"");
    }
    animate() {
        this.el.classList.toggle('inview');
    }
}

クラス内でanimate()を加え、DOMcontentLoaded内で呼び出す。

これで画面を読み込んだ際にinviewが付与される

開発ツールで確認したい時、setTimeoutを使うとよくわかる

setTimeout(() => {
    ta.animate();
    ta2.animate();
},2000)

この辺の概念はなれが必要だと思うので、自分の書いてきたjsのコード等でどんどん試してみようと思う。

ということで、おわり。

今日も良い一日を!