【こいつ…動くぞ!】おじさんと一緒にToDoアプリチュートリアル(4)【Vue.js】


ご覧いただきありがとうございます!UGと申します!

前回の「 おじさんと一緒にToDoアプリチュートリアル(3)」の続きです。

前回まで進めていただいた方、お疲れ様でした。


今回は、コンポーネント化(部品化)についての記事となります。

具体的には、前回作成したul/liについて、別ファイルのjsへ移し、そのファイルを読み込む、ということをやります。


※ html・css・JavaScriptが何となく書ける方向けです
※今回、vue-cliは使用しません。基本的なVueの機能を体感したい、という人向けです。

1.本記事でのゴール!と実装する上での考え方

最終的なゴール

最終的なゴールは上記gif画像の通りです。前回と同様です。

1.Vueを使って文字を表示する
2.inputタグに入力した文字をブラウザ上に反映させる
3.todoリストを表示させる
4.todoリストに表示させる部品を作成する
5.inputタグに入力した文字をtodoリストへ反映させる
6.削除ボタンを押す事でtodoリストからアイテムを削除させる

これらの動作を実装していきたいと思います!

本記事でのゴール!

本記事でのゴールは上記4・5

「 todoリストに表示させる部品を作成する」
「 inputタグに入力した文字をtodoリストへ反映させる 」

を目標にしていきたいと思います!
※5に関しては前回の記事でほぼ終了しています

実装する上での考え方


1.何も機能を持たない、「 Hello World 」と表示させるだけの部品を作成

2.ul・liタグを新たに用意するjsファイルに移す

3. ul・li タグへ送るデータを別ファイルに送り出す(propする)

2.今回のファイル構成

test
│  index.html
│
└─js
    index.js
    list-item.js


前回のファイル構成へ、「list-item.js」というファイルを加えました。

今回は、このlist-item.jsに、ul・liタグを移し、配列となっているtodoリストデータを渡していきます!

3.部品化(コンポーネント化)したモノを作成!呼び出す!

list-item.jsを用意し、下記のように編集する

Vue.component('list-item', {
  template:`
    <p>hello world</p>
  `
})

Vueでは任意の機能を持たせて、別ファイルとして作成、呼び出すことができます。

HTML・JS共に見やすくなり、開発もやりやすくなります。


コンポーネントしたい内容を、上記のように、「Vue.component」で囲み、表示させたい内容をcomponentへ記載します


componentとしての名称は、上記リストのlist-itemの部分に相当し、呼び出すhtmlにて

<list-item> </list-item>

というタグ構成にて呼び出すことができます!
※今回の記事を手を動かしながら読み進めると実感できるかと思います!

index.htmlにてlist-itemをscriptで呼び出し、hello worldを表示する

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>hello!!!</h1>
 
    <div id="app">
      <div id="message">
        <input type="text" v-model="message" />
        <button
          v-on:click="addTodoList"
          v-bind:disabled="isDisabled"
        >
          todoリストに加える
        </button>
        <p>{{ message }}</p>
      </div>
      <!-- ul liタグを用意する -->
      <div class="todo">
        <ul class="todo-content">
          <li
            class="todo-content-item"
            v-for="item in list"
            v-bind:key="item.id"
          >
            {{ item.id }}:{{ item.text }}
          </li>
        </ul>
      </div>
      <list-item></list-item>
    </div> 
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="./js/list-item.js"></script>
    <script src="./js/index.js"></script>

  </body>
</html>


前回最終コードに、list-itemタグと、list-item.jsを読み込むためのスクリプトを記載しました(34行目と37行目)

上記のようにlist-item.jsの作成、index.htmlへのコード追加することによって、list-item.jsに記載したpタグのhello worldが表示されます。

次の工程で、pタグをul・liタグに変更し、表示todoリストを表示させましょう!

4.配列データをpropしてコンポーネントで表示する!

ちょっと何言ってるかわかんない

と思われる方もいるかもしれません。

index.js(親ファイル)からlist-item.js(子ファイル)へデータを渡すことをpropする、と表現します。

ここではtodoリストを表示するために前回作成した配列、「list」をコンポーネントへpropします。

propしたデータをul・liタグ内でv-forを用いて表示させます。

list-item.jsを編集する

Vue.component('ListItem', {
  template: `
  <ul>
    <li
      v-for="item in list"
      v-bind:key="item.id"
    >
      {{ item.id }}:{{ item.text }}
    </li>
  </ul>
  `,
  props:['list'],
});

list-item.jsを上記のように編集してください。

ここでは、「list」というデータをpropsで受け取り、template内のv-forでデータを表示させていることがわかるかと思います。
※v-forに関しては前回の記事を参照してください。

重要なモノはやはりpropsですが、上記の通り、シンプルに使用することができます。

そしてtemplate内では、vueのテンプレート構文が使用できます。

propsでデータをtemplateに渡して、それをtemplate内で扱う、それだけでいろんな表現ができます。

実際にhtmlとして表現させるには、props:[list]をバインドさせることで、値を渡します。

※コンポート名をパスカルケースで指定しています。こうすることで、htmlにて呼び出す際に、<list-item />、 <ListItem />双方どちらでも呼び出すことが出来るようになります。

list-item.jsを編集する

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>hello!!!</h1>
 
    <div id="app">
      <div id="message">
        <input type="text" v-model="message" />
        <button
          v-on:click="addTodoList"
          v-bind:disabled="isDisabled"
        >
          todoリストに加える
        </button>
        <p>{{ message }}</p>
      </div>
      <!-- ul liタグを用意する -->
      <div class="todo">
        <list-item
          v-bind:list="list"
        />
      </div>
    </div> 
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="./js/list-item.js"></script>
    <script src="./js/index.js"></script>
  </body>
</html>


今までul・liタグがあったところを「list-item」タグに置き換えています。

list-itemタグにてコンポーネントを呼び出し、list-itemにて設定している「list」をバインドしています。

子は 「props指定したものでデータを受け取り」、
親は「子でprops指定したものをbindして渡す」といった感じです。

ここまで編集したら、今回の目標である「todoリストに表示させる部品を作成する 」は達成です!!!


5.子コンポーネントでdata型を設置、methodを呼び出してみる!


前章にて、今回の目標は達成しました。

この章では、次回の準備と、コンポーネントでもmethodを自由に作成、呼び出すことが出来る、ということを実感していただければと思います!!

index.htmlにボタンを用意して、 v-on:click=”addTodoList” を加えてあげる

list-item.jsを編集してmethodを呼び出してみる

Vue.component('ListItem', {
  template: `
  <ul>
    <li
      v-for="item in list"
      v-bind:key="item.id"
    >
      {{ item.id }}:{{ item.text }}
      <button
        v-on:click="sampleMethod()"
      >
        sampleメソッドを呼び出す
      </button>
    </li>
  </ul>
  `,
  props:['list'],
  data:()=>({
    sample: 'sampleメソッドです'
  }),
  methods: {
    sampleMethod() {
      console.log(this.sample);
      window.alert(this.sample);
    }
  },
});

上記のようにlist-item.jsを編集(10行目、18行目以降を編集しています)し、ブラウザをリロードしてください。


todoリストの右側にボタンが現れました。
クリックすると、data型で指定したsampleデータがコンソールとアラートに表示されるはずです。


コンポーネントでも、上記のようにmethodやdata型等々設置することが出来ます!!

使用方法は今までお伝えした通りの使用方法で使用できます!!


まとめ

本記事での最終的なコード

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>hello!!!</h1>
 
    <div id="app">
      <div id="message">
        <input type="text" v-model="message" />
        <button
          v-on:click="addTodoList"
          v-bind:disabled="isDisabled"
        >
          todoリストに加える
        </button>
        <p>{{ message }}</p>
      </div>
      <!-- ul liタグを用意する -->
      <div class="todo">
        <list-item
          v-bind:list="list"
        />
      </div>
    </div> 
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="./js/list-item.js"></script>
    <script src="./js/index.js"></script>
  </body>
</html>
new Vue({
  el: "#app",
  data: () => ({
    message: "sample",
    list: [
      { id: 1, text: "todoリスト1" },
      { id: 2, text: "todoリスト2" },
    ],
  }),
  methods: {
    addTodoList() {
      // 現在の配列の個数から、次のid番号を取得する
      const nextId = this.list.length + 1;
      // v-modelで入力されたmessageを新たなtodotextとする
      const todoText = this.message;
      // listと同様のオブジェクトにする
      const newTodo = {id:nextId, text: todoText};
      // 配列に加える
      this.list.push(newTodo);
      this.message = '';
    }
  },
  computed: {
    isDisabled() {
      if(this.message.length <= 0) {
        return true;
      } else {
        return false;
      }
    }
  },
});
Vue.component('ListItem', {
  template: `
  <ul>
    <li
      v-for="item in list"
      v-bind:key="item.id"
    >
      {{ item.id }}:{{ item.text }}
      <button
        v-on:click="sampleMethod()"
      >
        sampleメソッドを呼び出す
      </button>
    </li>
  </ul>
  `,
  props:['list'],
  data:()=>({
    sample: 'sampleメソッドです'
  }),
  methods: {
    sampleMethod() {
      console.log(this.sample);
      window.alert(this.sample);

    }
  },
});

いかがだったでしょうか

本記事にて

・componentの方法!
・componentの呼び出し方!
・親から子へのデータ渡し「 props 」!

を紹介いたしました!

次回は、todoリストを削除する機能を実装したいと思います!!

それでは、今回はここで失礼いたします!