vuejsお勉強メモ

rails&laravel mixで環境作って、ドットインストールのコースを一通りやってみた。コンポーネントむずい。

やったこと

  • 環境構築(rails + laravel mix)

qiita.com

  • ドットインストールのvuejsのコース一通り。todoアプリ作成&いいねボタン作成とカウントなど

github.com

コンポーネントとは???

コンポーネントは名前付きの再利用可能な Vue インスタンスです

jp.vuejs.org

コンポーネント指向とは

f:id:shimabukuromeg:20180816224105p:plain

なんとなくの理解

  • html側でdiv要素を書いて、適当なidをつける。vuejs側は、vueのインスタンスを生成するときに、html側のdiv要素(element)のidを指定する。そうすると、UI側(UI側???って表現があってるかわかんないけど、html側)とvuejs側が紐づいて、vuejs側で持ってるデータ (配列)とかメソッドを利用できるようになる。

jp.vuejs.org

  • v-model だとか v-for とか v- から始まる特殊な属性をディレクティブと呼ぶ。(html側に書くやつ)

  • submit された時のイベントですが、イベントを紐付けるには v-on というディレクティブを使う(v-on はよく使うので @ で @submit のように省略)このとき、イベントが発生して呼び出すメソッドは、vuejs側のvueインスタンスの、method: {} の中に定義する。

f:id:shimabukuromeg:20180817081711p:plain

  • データに応じてクラスを付け替えるには、 v-bind:class というディレクティブを使う。<span v-bind:class="{done: todo.isDone}"> これはtodo.isDoneがtrueだったら、spanタグのclassにdoneを付与する。

  • <li v-show="!todos.length">Nothing to do, yay!</li> v-showディレクティブ。これは!todos.lengthがtrueだったら、Nothing to do, yay!が表示されるってやつ

  • 部品を再利用するために Component っていう機能を使う

  • Componentの機能を使うとき、まずhtml側では、vueのインスタンス作成するときに紐付けたdiv領域の中で、適当なオリジナル要素を作成する。例えば、<like-component></like-component> のような感じ。ここの部分をvuejs側から操作できるようになるイメージ。

  • vuejs側はどんな感じにするのかっていうと、最初にvueのappのインスタンスを作成したやつの中に、components: { 'like-component': likeComponent } って書いて、コンポーネントを使うよって定義してあげる。ここで定義したやつを、vueのappのインスタンスの上の方で定義する。例えば、Vue.extend としてあげて、その中にどの中身を入れたいかは、 template で書く。このtemplateに書いたやつが、最初にhtml側で書いた <like-component></like-component> の中で表示されるようになる。

  • さらにmethodとかデータを使いたかったら、Vue.extend したvueのインスタンスの中にいろいろ書いていく。

    var likeComponent = Vue.extend({
        // props: ['message'],
        props: {
          message: {
              type: String,
              default: 'Like'
          }
        },
        data: function () {
            return {
                count: 0
            }
        },
       template: '<button @click="countUp">{{ message }} {{ count }}</button>',
        methods: {
           countUp: function () {
               this.count++;
               this.$emit('increment');
           }
        }
    });

ドットインストール vuejsのコース一通りやったらできるtodoアプリのコード。

app.js

require('./bootstrap');

window.Vue = require('vue');

Vue.component('example-component', require('./components/ExampleComponent.vue'));

document.addEventListener("DOMContentLoaded", function () {

    var likeComponent = Vue.extend({
        // props: ['message'],
        props: {
          message: {
              type: String,
              default: 'Like'
          }
        },
        data: function () {
            return {
                count: 0
            }
        },
       template: '<button @click="countUp">{{ message }} {{ count }}</button>',
        methods: {
           countUp: function () {
               this.count++;
               this.$emit('increment');
           }
        }
    });
    var vm = new Vue({
        el: '#app',
        components: {
          'like-component': likeComponent
        },
        data: {
            newItem: '',
                todos: [],
            total: 0
        },
        watch: {
            todos: {
                handler: function () {
                    localStorage.setItem('todos',JSON.stringify(this.todos));
                },
                deep: true
            }
        },
        mounted: function () {
            this.todos = JSON.parse(localStorage.getItem('todos')) || []
        },
        methods: {
            addItem: function () {
                var item = {
                    title: this.newItem,
                    isDone: false
                };
                this.todos.push(item);
                this.newItem = '';
            },
            deleteItem: function (index) {
                if (confirm(('agre you sure?'))) {
                    this.todos.splice(index, 1);
                }
            },
            purge: function () {
                if(!confirm('delete finished?')){
                    return;
                }
                this.todos = this.remaining;
            },
            incrementtotal: function () {
                this.total++;
            }
        },
        computed: {
            remaining: function () {
                return this.todos.filter(function(todo){
                    return !todo.isDone
                });
            }
        }
    });
});

index.html.erb

<div class="container">

  <div id="app">
    <p>Total Likes: {{ total }}</p>
    <like-component message="Like" @increment="incrementtotal"></like-component>
    <like-component message="Awesome" @increment="incrementtotal"></like-component>
    <like-component message="Great" @increment="incrementtotal"></like-component>
    <like-component @increment="incrementtotal"></like-component>
    
    <h1>
      <button @click="purge">Purge</button>
      My Todo
      <span class="info">({{ remaining.length }}/{{ todos.length }})</span>
    </h1>
    <ul>
      <li v-for="(todo, index) in todos">
        <input type="checkbox" v-model="todo.isDone">
        <span v-bind:class="{done: todo.isDone}">
          {{ todo.title }}
        </span>
        <span @click="deleteItem(index)" class="command">[x]</span>
      </li>
      <li v-show="!todos.length">Nothing to do, yay!</li>
    </ul>

    <form @submit.prevent="addItem">
      <input type="text" v-model="newItem">
      <input type="submit" value="Add">
    </form>
  </div>

</div>