vuejsお勉強メモ
rails&laravel mixで環境作って、ドットインストールのコースを一通りやってみた。コンポーネントむずい。
やったこと
- 環境構築(rails + laravel mix)
- ドットインストールのvuejsのコース一通り。todoアプリ作成&いいねボタン作成とカウントなど
コンポーネントとは???
- コンポーネントとは???うーんむずい
コンポーネント指向とは
なんとなくの理解
- html側でdiv要素を書いて、適当なidをつける。vuejs側は、vueのインスタンスを生成するときに、html側のdiv要素(element)のidを指定する。そうすると、UI側(UI側???って表現があってるかわかんないけど、html側)とvuejs側が紐づいて、vuejs側で持ってるデータ (配列)とかメソッドを利用できるようになる。
v-model だとか v-for とか v- から始まる特殊な属性をディレクティブと呼ぶ。(html側に書くやつ)
submit された時のイベントですが、イベントを紐付けるには v-on というディレクティブを使う(v-on はよく使うので @ で @submit のように省略)このとき、イベントが発生して呼び出すメソッドは、vuejs側のvueインスタンスの、
method: {}
の中に定義する。
データに応じてクラスを付け替えるには、 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>