LoginSignup
18

More than 1 year has passed since last update.

Vue.js 勉強メモ こういう事が知りたかった!を中心に

Last updated at Posted at 2021-04-28

はじめに

仕事で使う事になったので1からVue.jsについて学んだ際にちゃんと覚えておかないとまずそうな事がいくつかあったのでそれを備忘録として残しておく。

Index(各記事へのリンク)

お勉強リポ

細かくコミットを区切っているので、Vue.jsのポイントとなる概念・構文についてそれぞれをソースベースで見れる。

Vue API レファレンス

複数のVueインスタンスを作成する際の注意

以下のように、複数のVueインスタンスを作成する事はできるが、

  • 相互に独立しており、依存関係(関連性)がない場合

に基本的には使うようにする。Aというインスタンスの値が変更されたらBというインスタンスに反映させる、という事は技術的には可能だが、複雑になるのでやらないようにすべき。

sample.html
<body>
    <div id="app1">
        <p>{{message}}</p>
    </div>

    <div id="app2">
        <p>{{message}}</p>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
    <script>
        new Vue({
            el: '#app1',
            data: {
                message: 'インスタンス1'
            }
        })

        new Vue({
            el: '#app2',
            data: {
                message: 'インスタンス2'
            }
        })
    </script>
</body>

Vueインスタンスのプロパティ

VueインスタンスにはVue側であらかじめ用意されているプロパティがあり、$で始まるものがそれ。
(以下はconsole.log()でVueインスタンスの中身を出力させた結果。)

例1 例2
image.png image.png

これらのプロパティへはインスタンスの内部・外部の両方から以下のようにアクセスできる。
image.png

sample.html
<body>
    <div id="app1">
        <p>{{message}}</p>
        <p>{{name}}</p>
        <p>{{myData}}</p>
    </div>

    <script src=" https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
    <script>
        const data = {
            message: 'こんにちは',
            name: 'こんばんは'
        }

        const vm = new Vue({
            el: '#app1',
            data: data,
            computed: {
                myData: function () {
                    // プロパティへ内部からアクセスの例。"this.$○○"の形式でアクセスする。
                    return this.$data;
                }
            }
        })

        // Vueインスタンスのプロパティへ外部からアクセスの例。以下は"true"になる。
        console.log(data === vm.$data);
    </script>
</body>

※Vueインスタンスのプロパティの詳細はこちらを参照

$mountメソッドの利用場面

$mountメソッドを用いると、Vueインスタンス作成後にelプロパティを設定できるが、これは

  • 動的にVueインスタンスの対象を変更したい
  • Vueインスタンスが作成された時にはまだHTML上に要素がないようなものに対し後からマウントする(表示させる)

といった場面で用いる。

※ただし、基本的にはVueインスタンス作成時にelプロパティで指定するようにする

sample.html
<body>
    <div id="app">
        <p>{{message}}</p>
    </div>

    <script src=" https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
    <script>
        const vm = new Vue({
            data: {
              message: 'こんにちは'
            },
        })
        vm.$mount('#app')
    </script>
</body>

※実はmountは、仮想DOMを実際のDOMに反映させるという事をしている。(elプロパティでも同じ)。これにより仮想DOMがDOMとして構築され実際に画面が描画されるという仕組みになっている。

Vue.jsにおけるHTML描画の方法3つ

Vue.jsにはHTMLをレンダリングさせる方法が3つある。それぞれ実装方法は違うがいずれも同じように画面が描画される。
※このそれぞれの方法でのHTML描画をtemplateと呼んだりし、templateを`render関数に変換すると言ったりする。

# やり方
1 HTMLに直接記述
2 templateプロパティに文字列を記述
3 render関数でVNode(仮想ノード)をreturn

1 HTMLに直接記述

今までやってきたように直接記述する。

sample.html
<body>
    <div id="app1">
        <h1>こんにちは、{{name}}</h1>
    </div>

    <script src=" https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
    <script>
        new Vue({
            el: '#app1',
            data: {
              name: '田中 太郎'
            }
        })
    </script>
</body>

2 templateプロパティに文字列を記述

以下のようにtemplateプロパティに文字列を記述する。

sample.html
<body>
    <div id="app2"></div>

    <script src=" https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
    <script>
        new Vue({
            el: '#app2',
            data: {
              name: '田中 太郎'
            },
            template: '<h1>こんにちは、{{name}}</h1>'
        })
    </script>
</body>

3 render関数でVNode(仮想ノード)をreturn

以下のようにrenderプロパティVNode(仮想ノード)をreturnさせる。

sample.html
<body>
    <div id="app3"></div>

    <script src=" https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
    <script>
        new Vue({
            el: '#app3',
            data: {
              name: '田中 太郎'
            },
            render: function (h) {
                return h('h1', `こんにちは、${this.name}`);
            }
        })
    </script>
</body>

render関数とVue.jsの仮想DOM

render関数の部分でVNode(仮想ノード)という話が出たが、これは速度向上などのためにVue.js側で備えている仕組みである仮想DOMに関連するもの。この仮想DOMについて背景にある問題も踏まえてまとめておく。

前提

document(ブラウザのオブジェクト)に直接アクセスして、それに対し要素の新規作成・更新・削除したりする処理は遅い。
そのため何かが変更されるたびにDOMを全てを再描画していたのでは処理が遅くWebサイトとして使用感が悪いものになる。

ではどうするか?

  • 変更の前後でDOMの差分を見比べ、差分がある部分だけ実際のDOM書き換える

というように、変更された部分だけDOMを書き換えるという方法が考えられる。
この方法(仕組み)を実現するために仮想DOMというものがある。
つまりVue.jsでは、変更の前後で仮想DOMを比較し差分があるか?をチェックし、差分があればその特定個所のみ実際のDOMを変更する、という仕組みにする事で高速化を実現している。

仮想DOMとは?

  • DOM要素を模したJavaScriptのオブジェクト

であり、JavaScriptのオブジェクトであるが故にそこへアクセスは高速に行えるので高速化が実現できる。仮想DOMはVNode(仮想ノード)の集合体のイメージでよく、ノード=節という事から分かるようにノードはDOMを構成する要素。

仮想DOMがないとどうなるか?

仮想DOMがない場合を考えると、Vue.jsでどこが変更されたか?の特定ができなくなり、変更毎に変更後のものに基づきDOMを全部再描画しないといけなくなり処理が遅くなる(使用感が悪くなる)。
言い換えると、バニラJavaScriptで明示的にDOMの一部のみを変更した時と同じ速度で、Vue.jsでもあらゆる要素の変更に対する再描画を行うために仮想DOMがある。

※バニラJavaScriptで明示的にDOMの一部のみを変更した時 とは以下のようなソースコードの処理の事。

sample.html
<body>
    <div id="app1"></div>
</body>
sample.js
const app = document.querySelector('#app'); 
app.innerHTML = '<p>Hello</p>';

Vue.jsにおける仮想DOMのメリット

  • Webサイトの動作の高速化(使用感の向上)
  • render関数が使える
  • ブラウザ以外の環境に対応しやすい
  • 変更前後の仮想DOMを比較し変わっていなければ何もしないという処理も実現可能

documentと仮想DOMというそれぞれのオブジェクトの違い

# 説明 特徴
document ブラウザが標準で備えているオブジェクト ここへのアクセスは処理コストが高く遅い
仮想DOM JavaScriptのオブジェクト ここへのアクセスは処理コストは低く速い

実はrender関数以外のHTML描画の方法も内部的な動きはrender関数と同じ

前セクション(Vue.jsにおけるHTML描画の3つの方法)で3つの実装方法を見たが、実は内部的な動きでは1, 2もrender関数が動きVNode(仮想ノード)化されて、それがVueに渡され仮想DOMになり、最終的にDOMに変換されて画面に描画される。

親・子間のデータ(slotを介すものも含む)受け渡しを行う際にはこれが基本パターン

基本的には、以下の順によく使われる。

  1. 親→子へのデータ渡し・html要素の渡し(props・template/slot)
  2. 子→親のデータ渡し($emit)
  3. 子→親のデータ渡し(template・slotの場合のslotプロパティ)

※できるだけslotでデータを子→親で渡すとかはしないほうがいい。
※できる事・機能と実際にどのようにプロダクトコードを書いていくのか?は別物であり、できるだけシンプルに書く方が後で楽になる。

カスタムディレクティブの使い処

  • コードの再利用を行いたい
  • コンポーネントにするよりディレクティブの方が良い

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18