Vueの設定ファイルが読みたい...。JSの基礎を学びつつRails * Vueの設定ファイルを読んだ話


### これは何？

RailsアプリにVueを組み込んで実装していますが、いまいち効率が良くない気がしました。
新しい設定ファイルの書き方を探していた時に見つけた[これちらの設定ファイル](https://note.com/campfire_dev/n/n1686059962b5)が読めなかったので、読み方を確かめがてら、jsの基本文法について学びました。

▼参考にした設定ファイル

```js:
import Vue from "vue";
import Hoge from './components/Hoge';
import Fuga from './components/Fuga';

export const components = {
  Hoge,
  Fuga
};

document.addEventListener("DOMContentLoaded", () => {
  let templates = document.querySelectorAll("[data-vue]");

  for (let el of templates) {
    let app = new Vue(components[el.dataset.vue]);
    app.$mount(el);
  }
});
```
このファイルで、これらのコンポーネントを読み込んでいます。

```erb:
<%= javascript_include_tag webpack_asset_path('app.js') %>

<main>
  <div data-vue="Hoge"></div>
  <div data-vue="Fuga"></div>
</main>
```

なお、本記事の内容は主に[MDN](https://developer.mozilla.org/en-US/)に出てきた内容と、[こちらのYouTube動画](https://www.youtube.com/watch?v=De9PH3EAz7c&list=PLwM1-TnN_NN4SV6DEs4OtfA51Up6XzTfB)の内容を元にまとめたものです。

## マウントとは
既存のDOM要素をVue.jsが生成するDOM要素で置き換えること。引用した設定ファイルでもマウントをして、JSで生成した要素をビューに表示しています。

### elプロパティによるマウント

`Vue`インスタンスを新規作成した際に、`el`で指定したDOM要素に`vue`で生成したコンポーネントを新規マウントさせる。

```vuejs:
var vm = new Vue({
  el: '#app'
})
```
この場合は、新規作成したインスタンスを`#app`にマウントさせています。
なお、`vm`は**VueModel**の略で、Vue インスタンスの変数名としてよく使われます。

### $mount() メソッドによるマウント

```js
var vm = new Vue({
  // data: などいろいろ
})
vm.$mount(el)
```

こちらも、要素をマウントさせる書き方の一つです。`el`プロパティによるマウントと違い、**新規作成以外の任意のタイミングでマウントできること**が特徴です。

## inport
別の`JS`（cssや画像のことも）ファイルから要素を取り込むときに`import`で取り込みます。その時の書き方がたくさんあります。

### 名前付きインポート(named_import)
まずは、このように`{}`付きで書かれるパターン。これは**「名前付きインポート」**と言います。

```js
import { hoge } from "./fuga.js"
```
この時、`fuga.js`にはこのように書かれています。

```js:fuga.js
const hoge = "変数の中身"
export { hoge }
```
このように、変数の宣言と同時に`export` することもできる。

```js:fuga.js
export const hoge = "変数の中身"
// export { hoge }
```
2つ以上一気に`export`, `import`することもできる。

```js
import { hoge1, hoge2 } from "./fuga.js"
```
```js:fuga.js
const hoge1 = "変数の中身1"
const hoge1 = "変数の中身1"

export { hoge1, hoge2 }
```
関数も`export`できる。

```js:fuga.js
function hello1(value) {
  console.log(value)
}

export function hello2(value) {
  console.log(value)
}

export { hello1 }
```

```js
import { hello1, hello2 } from "./fuga.js"

hello1("こんにちは")
hello1("おはよう")

// consoleに”こんにちは”、”おはよう”と表示される
```
こんな風にすると、エイリアスがつけられる。

```js:fuga.js
const hoge1 = "変数の中身1"
export { hoge1 }
```
```js:
import { hoge1 as ho } from "./fuga.js"
console.log(ho)
```
今回は`import`する側でエイリアスをつけたが、`export`する側でもエイリアスがつけられる。（わかりにくいので略）

### デフォルトexport

`named export`と書き方が違うのは２つ。１つは、`export`側で`export default`と書くこと。

```js:fuga.js
const hoge = "変数の中身"
export default hoge;
```
もう一つは、`import`側で`{}`を外すこと。

```js
import hoge from "./fuga.js"
```
また、`default export`が`named export`と大きく違うのは、
`default export`は１モジュールに対して1回しかexportを使うことができない。
つまり、これはできない。

```js:fuga.js
const hoge1 = "変数の中身1"
const hoge2 = "変数の中身2"

export default hoge1;
export default hoge2;
```

また、`default export`の場合、`import`する側では識別子（今回の場合、hoge1とかhoge2とか）に好きな名前を付けることができる。

```js:fuga.js
const hoge = "変数の中身"
export default hoge;
```
```js
import fuga from "./fuga.js"
```

これは、`default`が`hoge`という変数ではなく、**評価された値**（ここでは「変数の中身」という文字列）を読み込んでいるため。

### 関数の default export
関数も`default export`できます。

```js:fuga.js
function hello(value) {
  console.log(value)
}

export default hello;
```
```js
import hello from "./fuga.js"

hello("こんにちは")

// consoleに”こんにちは”と表示される
```
好きな名前で`import`もできます。

```js
import hi from "./fuga.js"

hi("こんにちは")

// consoleに”こんにちは”と表示される
```

宣言と同時に`export`するときは、識別子が不要です。
コンポーネントでよく見る形だわ。。。

```js:fuga.js
// 無名関数(識別子がない)
export default function(value) {
  console.log(value)
}
```
```js
import hello from "./fuga.js"

hello("こんにちは")

// consoleに”こんにちは”と表示される
```

### `el.dataset.vue`について

HTMLの`data-xxx`プロパティに書かれている項目を`el.dataset.xxx`の形で取得できる。属性なので getAttribute() でも扱えるが、`el.dataset.xxx`はカスタムデータ属性専用のメソッド。

```js:
console.log(el.getAttribute('data-foo'));  // => "123"
console.log(el.dataset.foo);               // => "123"
```

▼参考：
[data属性を扱うならdatasetで楽ちん。（DOMおれおれAdvent Calendar 2015 – 17日目）](https://ginpen.com/2015/12/22/dataset/)

## 連想配列のキー取得方法

最後に、JSでの連想配列でのキー取得方法について。
こんな連想配列があったら。。。

```js:
let member1 ={name:'太郎',age:'39',sex:'male'}
```
キーはこんな書き方で取得するそうです。

```js:
console.log(member1.name)
console.log(member1['name'])
```
▼[JavaScriptでの連想配列(オブジェクトリテラル)の書き方・使い方について解説](https://www.e-loop.jp/knowledges/25/)

## 改めて、最初のコードを読んでみる

さて、知識は集まったと思うので、改めて最初の設定ファイルを読んでみます。

```js:
import Vue from "vue";
import Hoge from './components/Hoge';
import Fuga from './components/Fuga';

export const components = {
  Hoge,
  Fuga
};

document.addEventListener("DOMContentLoaded", () => {
  let templates = document.querySelectorAll("[data-vue]");

  for (let el of templates) {
    let app = new Vue(components[el.dataset.vue]);
    app.$mount(el);
  }
});
```

まず、この部分は

```js:
import Hoge from './components/Hoge';
import Fuga from './components/Fuga';
```
**デフォルトexport**で、`Hoge.js`、`Fuga.js`の**評価された値**をそれぞれ、`Hoge`、`Fuga`という変数で読み込んでいます。

そして、定義した変数を

```js:
export const components = {
  Hoge,
  Fuga
};
```

`components`という変数の中にいれ、宣言と同時に`export`しています。

```js:
document.addEventListener("DOMContentLoaded", () => {
  let templates = document.querySelectorAll("[data-vue]"); // ★1

  for (let el of templates) { // ★2
    let app = new Vue(components[el.dataset.vue]); //★3
    app.$mount(el); // ★4
  }
});
```

**★１**で、コンテンツが読み込まれたときに、`data-vue`属性のついている要素を`templates`変数にそれぞれ格納し、

**★2**で、それぞれを変数`el`に格納しつつ宣言して`for`で回します。

最後に**★3**で、連想配列`components` から`[el.dataset.vue]`の内容（評価されたHoge.jsとFuga.jsの値）を取り出して、`Vue`インスタンスを作成し、

生成したVueインスタンスを、`$mount()`メソッドで`el`（data-vue="Hoge", data-vue="Hoge"のついた<div>要素）にマウントしています(★4)。


長かったですが、これでVue.jsの設定ファイルを読むことができました。