Vue.js基礎

#Vue.jsの基礎
###環境と参考文献
Vue.jsの学習における基礎の振り返りと脳内整理の為に記す。
環境
M1 MacBookAir
Vue.js Ver 3.15
参考文献： Vue.js プロフェッショナル Webプログラミング

基本的にCDNでVue.jsをインポート
componentについては別途、書いていこうと思います。

###dataプロパティ
Vueインスタンス作成時にdataオプションにオブジェクトを返す関数を定義することで、dataの状態を定義できる
このデータを更新、加工して基本的にVue.jsはデータを扱う

```.js
Vue.createApp({
    data: function() {
        return {
            key: '値'
        }
    }
})
```

Vueアプリケーションはオブジェクトのプロパティがアクセス、変更されることを検知できるようになる。
HTMLに出力するには

```.html
<div id="app"> {{ key }} </div>
```

マウントした要素ないであれば　{{ }} でHTMLに出力ができる。

###computedプロパティ
管理しているデータを加工、検証する場合に有効なプロパティである。

```.js
Vue.createApp({
    data: function() {
        return {
            key: '値'
        }
    },
    computed: {
        key: function() {
            //処理
        },
    },
})
```

######なお、後述するmethodsとはプロパティとメソッドと明確な違いがあるが、使い分けで混乱するので、
######プロパティ操作はcomputed アクション処理はmethodで初心者は使い分けを行うのが無難であると思う。
また、computedプロパティは、監視している値に変化がない場合はキャッシュ(前回の値)を返す為、
ユーザ操作による値の変更がない処理などは一度しか実行されないので注意。
例：日時処理をするdataFormatプロパティは実行した日時を元に処理している為、
一度しか実行されない。

###methodsプロパティ
何らかの処理をする際に使用する。
例えば、ユーザがボタンを押した際にdataを変更したり、dataの変更と同時に他の処理をしたい場合に使用
あくまで、メソッドなので処理後に値を保持することはない。逆にcomputedプロパティはプロパティなので、値を保持することが
可能である。要は、毎回実行されるため、キャッシュを使用せずに、処理した結果が帰ってくる。

```.js
Vue.createApp({
    data: function() {
        return {
            key: '値'
        }
    },
    methods: {
        key: function() {
            処理
        }
    }
})
```

###watchプロパティ
dataやcomputedのプロパティの値を監視して、変更があれば任意の処理を実行させる事ができる。
値にはオブジェクトを取り、監視したいdataやcomputedのプロパティ名をそのまま指定して、
関数を指定するのが基本形である。
引数には第一引数に新しい値と第二引数に古い値を受け取る事ができる

```.js
Vue.createApp({
    data: function() {
        return {
            key: '値'
        }
    },
    watch: {
        key: function(新しい値, 古い値) {
            処理
        },
    },
})
```

一つのオブジェクトの監視という点では、上記の指定で監視を行えるが、
配列にまとめたオブジェクト(ネストされたオブジェクト)の監視を行うには別途、指定が必要となる。
handlerオプションとdeepオプションの指定を行う。

```.js
Vue.createApp({
    data: function() {
        return {
            keys: [
                {
                    key: 1,
                },
                {
                    key: 2,
                },
            ],
        }
    },
    watch: {
        keys: {
            handler: function(新しい値, 古い値) {
                処理
            },
            deep: true,
        },
    },
})
```
watchへネストされたオブジェクトを指定して、handlerオプションで処理を指定。
deepオプションをtrueにすることで、ネストの深さに関係なく、オブジェクトの値を監視対象へ含めることが可能となる。

##ディレクティブ

DOM 要素に対して何かを実行することをライブラリに伝達する、マークアップ中の特別なトークンである。
HTMLに直接記述できる属性であり、省略形が存在するディレクティブもあるが、基本　v-　から始まる。

###v-bind
HTMLの属性を状態に応じて変更できる

```.js
//通常
v-bind:属性="値または式"
//省略形(:だけでもOK)
:属性="値または式"
```

値または式の部分には、dataやcomputedプロパティのオブジェクトのプロパティ名や、
methodsのプロパティ名に( )をつけた、関数呼び出しの式を指定する事ができる。
要は各プロパティに指定したオブジェクトを指定する。

ボタンの不活性化を例にすると

```.html
通常
<button v-bind:desabled="isDesablet">ボタン</button>
省略形
<button :desabled="isDesablet">ボタン</button>
```

```.js
Vue.createApp({
    data: function() {
        return {
           isDesablet: true,
        },
    }.
})
```

ここに、条件処理を追加すれば、ボタンの不活性化を制御できる。

class属性にv-bindを使用する際は、少し特殊で値に配列やオブジェクトも指定する事ができる。

####配列

```.js
//参考コード： Vue.js プロフェッショナル Webプログラミング
//v-bind:class="[プロパティ名、式]"の形で指定する

//HTML
<div :class="[className, 'selected', classNameComputed, classNameMethods()]}}">

//Vue.js
Vue.createApp({
    data: function() {
        return{
            className: 'from-data-class-name',
        }
    },
    computed: {
        classNameComputed: function() {
            return 'from-computed-class-name'
        },
    },
    methods: {
        classNameMethod: function() {
            return 'from-methods-class-name'
        }
    },
}).mount('#app')

//出力されるHTML
<div class="form-data-class-name 
            selected
            form-computed-class-name
            from-methods-class-name"
></div>
```

上記を見ると
dataプロパティに指定した className
通常のHTMLのclass属性にクラス名を与えた selected
computedプロパティに指定した classNameComputed
methodsに指定した classNameMethod
をまとめて配列で指定しているが、出力後のHTMLを見るとしっかりクラス名として出力されている。

逆にVue.js側に配列を持たせて、HTMLのクラス属性にプロパティ名を指定しても、問題なく配列はクラス属性の値として出力される。


####オブジェクト

```.js
v-bind:class="[プロパティ名：値]"//の形で指定する
```
先程の配列の場合は[プロパティ名、式]のどちらでも指定できたのに対し、
オブジェクトの場合は[プロパティ名:値]となる。
値にはdata,computedオブジェクトのプロパティ名,(  )をつけたmethodsのプロパティ名などを指定する。
この値が、true or falseでクラス名が付与されるかを制御する。


```.js
//参考コード： Vue.js プロフェッショナル Webプログラミング

//HTML
<div :class="'is-active': isActive, 'isinactive': !isActive"></div>

//Vue.js
Vue.createApp({
    data: function() {
        return {
            isActive: true,
        }
    },
}).mount('#app')

//出力されるHTML
<div class="is-active"></div>
```

オブジェクトの場合、dataの状態によってクラス名を動的に制御する事が多い為、computedのプロパティに
オブジェクト部分を指定する場合は多い

```.js
//参考コード： Vue.js プロフェッショナル Webプログラミング

//HTML
<div :class="className"></div>

//Vue.js
Vue.createApp({
    data: function() {
        return{
            isActive: false,
        }
    },
    computed: {
        className: function() {
            return {
                'is-active': this.isActive,
                'is-inactive': !this.isActive,
            }
        },
    },
})


```

また、HTMLの通常のクラス属性とv-bind:classは併用も可能で、
併用した場合は、通常のクラス属性で指定した値とv-bind:classで指定した値は両方とも
クラス属性に付与されて出力される為、併用の問題は可読性を下げる以外にあまりない。

style属性は割愛する。

###v-on
DOMのイベントを感知して、指定した処理を実行する事ができる。

```.js
//通常
v-on:イベント名="メソッド名"

//省略形
@:イベント名="メソッド名"
```

```.js
//参考コード： Vue.js プロフェッショナル Webプログラミング

//HTML
<button type="button" @click="onClickCountUp">CountUp</button>
//若くはHTML単体のみで動作できるなら(この場合は下のmethodsプロパティは丸ごといらない)
<button type="button" @click="count += 1">CountUp</button>
<p>{{ count }}</p>

//Vue.js
Vue.createApp({
    data: function() {
        return {
            count: 0
        }
    },
    methods: {
        onClickCountUp: function() {
            this.count += 1
        },
    },
})

```

基本的な使い方は上記の通りだが、上記の場合は暗黙的にmethodsプロパティのonClickCountUpに引数として$eventが渡されている。
渡さない方法、明示的に渡す方法を下記に簡単にまとめておく

```.js
//onClickCountUpに()を付けない場合は暗黙的に$eventが引数に渡される
<button type="button" @click="onClickCountUp">CountUp</button>

//onClickCountUpに()を付ける場合は$eventが引数に渡されない。というか何も渡してないので何も渡されない
<button type="button" @click="onClickCountUp()">CountUp</button>

//onClickCountUpに($event)を付ける場合は$eventが明示的に引数に渡される。
<button type="button" @click="onClickCountUp(＄event)">CountUp</button>
```

###v-model
v-bindとv-onをまとめて書きたい場合はv-modelでv-bindとv-onの機能を使用できる

```.js
v-model="プロパティ名"
```
```.js
//参考コード： Vue.js プロフェッショナル Webプログラミング

//HTML
<input type="text" v-model="message">
<p>{{ message }}</p>

//Vue.js
Vue.createApp({
    data: function() {
        return {
            message: '',
        }
    },
}).mount('#app')

```
上記はv-modelでinputイベントを取得し、messageへ反映している。
inputに文字を打てば、それに追従して、pタグの{{message}}が打った文字を反映して画面へ出力する。

下記記事を参考に、ここでは割愛する。
https://qiita.com/simezi9/items/c27d69f17d2d08722b3a


###v-for
配列やオブジェクトのデータを繰り返して、出力する事が可能である。

####配列
```.js
v-for="要素 in 配列"
```

```.js
//参考コード： Vue.js プロフェッショナル Webプログラミング

//HTML
<div v-for="item in items">{{ item }}</div>

//Vue.js
Vue.createApp({
    data: function() {
        return {
            items: ['item-1', 'item-2']
        }
    },
}).mount('#app')

//出力されるHTML
<div>item-1</div>
<div>item-2</div>
```

またindexが必要な場合はv-for="(要素, index) in 配列"として定義すれば、indexも使用できる。

####オブジェクト
```.js
v-for="要素 in オブジェクト"
```

```.js
//参考コード： Vue.js プロフェッショナル Webプログラミング

//HTML
<div v-for="value in object">{{ value }}</div>

//Vue.js
Vue.createApp({
    data() {
        return {
           object: {
               name: 'NAME',
               age: 20,
           }
        }
    },
}).mount('#app')

//出力されるHTML
<div>NAME</div>
<div>20</div>
```

オブジェクトを扱う場合はkey,value,indexを使用して繰り返し処理をすることもできる。
その場合は、v-for="(value, key, index) in object"で使用できる。
ここで言う、valueは'NAME'や２０ keyはname, ageとなる。
indexは配列と同様にindex番号である。

####:keyを指定して、効率化を図る
繰り返し処理は便利なのだが、配列、オブジェクト内の一つの値が変化すると基本的には配列全てを繰り返し処理を行わなければならない。
そこで、一意のkeyを用意することで、配列、オブジェクト内の要素を区別することができるようになる。
keyを付与すると、Vueは要素の変更前後の差分を検出し、効率のいい処理を行う事が可能となる。
※keyにはindexを使用しないこと。ソートやフィルターを使用して配列の順番が変化すると、意図した制御ができない可能性がある為、基本的には使用を避けること.

```.js
//参考コード： Vue.js プロフェッショナル Webプログラミング

//HTML
//v-bind:keyでidを取得することで、一意のデータとして紐つけできる
<div v-for="item in items" :key="item.id">{{ item.name }}></div>

//Vue.js
Vue.createApp({
    data: function() {
        return {
            items: [
                {
                    id: 1,
                    name:'item-1',
                },
                {
                    id:2,
                    name:'item2'
                }
            ]
        }
    }
}).mount('#app')
```

###v-show

```.js
v-show="値または式"
```
値にはdata,computedのプロパティ名、( )を付与した関数呼び出しのmethodsのプロパティ名を指定する事ができる。
HTMLの要素を表示非表示の切り替えが可能であり、CSSのdisplayプロパティを変更している。
つまりDOMは生成される。
単純にDOMに組み込まれて、CSSを変更しているだけなので、表示・非表示の切り替え頻度の高いものに対しては処理が軽いため、有効である。

```.js
//参考コード： Vue.js プロフェッショナル Webプログラミング

//HTML
<div v-if="isShow"></div>

//Vue.js
Vue.createApp({
    data: function() {
        return {
            isShow: false,
        }
    },
}).mount('#app')

//HTML出力結果
//表示されない
```

###v-if

```.js
v-if="値または式"
v-else-if="値または式"
v-else //条件指定以外
```

基本的な使い方はv-showと変わらない。
ただ、v-ifの場合には、条件に合わないものは、DOMに組み込まれない。
要はv-ifはHTMLの出力そのものを制御する。
v-ifは描画負荷が高い分、切り替え頻度の低いものに対して使用することが望ましい。
ただ、条件分岐が簡単に行えるので、そこは、v-showには無い利点である。

```.js
//参考コード： Vue.js プロフェッショナル Webプログラミング

//HTML
<div v-if="value >= 10">10以上</div>
<div v-else-if="value >= 5">5以上</div>
<div v-else>5未満</div>

//Vue.js
Vue.createApp({
    data: function(){
        return {
            value: 7,
        }
    },
}).mount('#app')

//HTML出力結果
<div>5以上</div>
```

###終わりに
Vue.js初学者なので、間違い等あったらご教授願えると幸いです。

かなり初歩的な部分を忘備録として書きましたが、ここまで読んで頂き、
長々とありがとうございました。