Vue.jsで始めるComponent入門

Vue.jsとは

背景

業務ではphpやgoといったサーバーサイドの技術を扱っているが、現状フロントのjavascriptの部分がサーバーサイドエンジニアかデザイナーが分担して書いている。コーディング規約があいまいなことからフロントエンドをちゃんと学び始めました。cssも学び中...

なぜVueか

UXの需要の高まりから複雑な動きをまとめたりシンプル化に繋げてくれるJavascriptフレームワーク界隈 その中ではVue.js, React.js, Angularjs, ember.jsなど様々なフレームワークが溢れています。 業務でのjavascriptではJqueryをメインに扱っていたので個人OSS且つコミュニティが盛んで学習コストが比較的 高くない理由からVue.jsを学びはじめました。

今後はフロントエンド界隈の基礎的なことを学びながらメモがてらブログに起こそうかと思います。

開発環境構築

環境はjs Fiddleでもローカル環境でも大丈夫です。 一つのプロジェクトを作るならVue CLIでプロジェクトを作ることをおすすめします。

// vue.jsを扱うためのコマンドラインインタフェースをインストールします。
$ npm install -g vue-cli

// プロジェクトを作成します。(このあとプロジェクト名やes-lint、ユニットテストの設定など聞かれますが特になければEnterで進みます)
// 上記でvue-routerを入れるかと聞かれる箇所は本記事では Noで進んでいただけると良いです。
$ vue init webpack vue-component-tutorial
$ cd vue-component-tutorial

// プロジェクト作成後 `package.json` からパッケージをインストールします。
$ npm install

// buildすることでdistフォルダが作成されこの後表示される画面のhtmlが作成されます。
$ npm run build

// ローカル環境を立ち上げます
$ npm run dev // デフォルト8080のポートでブラウザでアクセスすることができます。

ここまでがローカル環境での環境構築です。 基本的な操作はVueの公式ドキュメントでまとめられております。 日本語でも訳されていて使い方がとてもわかりやすいです。

jp.vuejs.org

作成したプロジェクトのsrc/main.jsを確認すると vueのインスタンスが作成されていることがわかります。

import Vue from 'vue'

new Vue({
  el: '#app',
  render: h => h(App)
})

Componentとは

早速Componentについて説明します。 Componentは,定義したタグ名で親となるComponentのhtml上に記述できます。 以下の例では app-user というタグ名でtemplateタグ内に記述したhtmlのコードを挿入することができます。

<div id="example">
  <app-user></app-user>
</div>
<template>
    <div class="component">
        <h1>The User Component</h1>
        /** 中略  **/
    </div>
</template>

Componentの登録手法

ここでは先ほどのapp-user コンポーネントを登録する方法を記載します。

import User from './components/User.vue';

Vue.component('app-user', {
    appUser: User
})

全てのコンポーネントをグローバルに登録する必要はなく、 例えばコンポーネント名のグローバルでの衝突回避や コンポーネントの中にコンポーネントがあるようなネストした状態の時にはローカルに登録します。

import User from './components/User.vue';

export default {
    components: {
        appUser: User
    }
}

Component間の通信

コンポーネントの中にコンポーネントがある状態を コンポーネントの親子関係と呼びます。

コンポーネントにはdataを持つことができます。 例えばこんな感じでオプションをつけるとデータやメソッドを持つことができます。

以下の例では User.vueはユーザのプロフィール画面の親コンポーネントです。

User.vue(js部分)

    import UserDetail from './UserDetail.vue';
    import UserEdit from './UserEdit.vue';

    export default {
        // データを持つことができます。
        data: function () {
            return {
                name: 'Kosa',
                age: 24
            };
        },
        methods: {
            // メソッドを定義できます。
            changeName() {
                this.name = 'Anna';
            }
        },
        components: {
            appUserDetail: UserDetail,
            appUserEdit: UserEdit
        }
    }

User.vue(html部分)

<template>
    <div class="component">
        <h1>The User Component</h1>
        <p>I'm an awesome User!</p>
        <button @click="changeName">Change my Name</button>
        <p>Name is {{ name }}</p>
        <p>Age is {{ age }}</p>
        <hr>
        <div class="row">
            <div class="col-xs-12 col-sm-6">
                <app-user-detail
                        :myName="name"
                        :userAge="age"
                ></app-user-detail>
            </div>
            <div class="col-xs-12 col-sm-6">
                <app-user-edit
                        :userAge="age"
                        @ageWasEdited="age = $event"
                ></app-user-edit>
            </div>
        </div>
    </div>
</template>

この時に使うプロパティはpropsというプロパティを使うことで子は親からのデータを受け取ることができます。 propsの中のリテラルで型の制御もすることができます。名前は文字列なのでstringでしか許容されないので以下のようなコードになります。

UserDetail.vue

<template>
    <div class="component">
        <h3>You may view the User Details here</h3>
        <p>Many Details</p>
        <p>User Name: {{ switchName() }}</p>
        <p>User Age: {{ userAge }}</p>
    </div>
</template>

<script>
    export default {
        props: {
            myName: {
                type: String
            },
            userAge: Number
        },
        methods: {
            switchName() {
                return this.myName.split("").reverse().join("");
            }
        }
    }
</script>

この時に使うプロパティは$emitというプロパティを使うことで子は親へデータを受け渡すことができます。 $emitの第一引数に送るデータの名前、第二引数にはそのデータをつけて親コンポーネントのUser.vueにデータを渡し、 @ageWasEdited="age = $event" でイベントデータをageに格納します。

UserEdit.vue

<template>
    <div class="component">
        <h3>You may edit the User here</h3>
        <p>Edit me!</p>
        <p>User Age: {{ userAge }}</p>
        <button @click="editAge">Edit Age</button>
    </div>
</template>

<script>
    export default {
        props: ['userAge'],
        methods: {
            editAge() {
                this.userAge = 30;
                this.$emit('ageWasEdited', this.userAge);
            }
        }
    }
</script>

以上でコンポーネントの操作の基本ができました。 完成形はこちらになります。 応用するとコンポーネントのライフサイクルフックを利用してコードを書くことで コンポーネントの状態をより密に書くことができます。

github.com

まとめ

まだvueのチュートリアルをしたぐらいですがコードの理解がしやすそうな印象を受けました。

次回にはライフサイクルの紹介やカスタムイベント、vue-routerなどに関しても紹介することができたらと思います。