LoginSignup
9
14

More than 5 years have passed since last update.

Vue.jsのコンポーネントの作り方(たぶん初級編)

Last updated at Posted at 2019-04-16

はじめに

 前回の記事「jQueryからVue.jsへ乗り換えてみた」の続きです。
 わかりやすいソースを目指しますが、わかりにくかったら言ってください。あと、レンタルサーバーなどで使うことも考慮しております。実は自分がレンタルサーバー使ってるので…。あとwebpackはまだ私も手を出していないです…。

とりあえずベタ書きしてみる

 前回の数字の入力が、フォームのテキストなので見栄えが微妙でしたのでVueコンポーネントを作ります。とりあえず0〜10までの値をボタンでを加減できるようにしてみましょう。
 

    Vue.component('toggle-button', {
        data() {
            return;
        },
        template: // コンポーネントの中身をHTML形式で書く
            '<div id="toggle-button">' +
            '   <button @click="set_value(-1)" v-bind:disabled="sub_disabled">ー</button>' +
            '   <span> {{ locale_string }} </input>' +
            '   <button @click="set_value(1)" v-bind:disabled="add_disabled">+</button>' +
            '</div>',
        props: {
            'value': {
                type: Number,
                required: true,
                default: 0
            },
            'locale_string': {
                type: String,
                required: true
            },
            'add_disabled': {
                type: Boolean,
                default: true
            },
            'sub_disabled': {
                type: Boolean,
                default: false
            }
        },
        computed: { // 自動計算
            locale_string: function () {
                // 表示は半角スペースをいれて2桁にしている。
                return `${`\u00A0${Number(this.value).toString()}`.slice(-2)}`; 
            },
            add_disabled: function () {
                // valueが10以上なら+をクリック無効にする
                return this.value >= 10;
            },
            sub_disabled: function () {
                // valueが10以上なら+をクリック無効にする
                return this.value <= 0;
            }
        },
        methods: { //メソッド(イベントなどを渡す関数)
            addValue: function (add) {
                this.value += add;
                // valueが変わったら呼び出し元に反映させるおまじない。
                this.$emit('input', this.value);
            }
        }
    })

 これで<toggle-button>タグがVueコンポーネントとして登録されます。
 実際に表示させるとこんな感じになります。
 image.png

 そして、これを前回のソースに反映させると…。

<!DOCTYPE html>
<html lang="jp">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<script>
    Vue.component('toggle-button', {
        data() {
            return;
        },
        template: // コンポーネントの中身をHTML形式で書く
            '<div id="toggle-button">' +
            '   <button @click="set_value(-1)" v-bind:disabled="sub_disabled">ー</button>' +
            '   <span> {{ locale_string }} </input>' +
            '   <button @click="set_value(1)" v-bind:disabled="add_disabled">+</button>' +
            '</div>',
        props: {
            'value': {
                type: Number,
                required: true,
                default: 0
            },
            'locale_string': {
                type: String,
                required: true
            },
            'add_disabled': {
                type: Boolean,
                default: true
            },
            'sub_disabled': {
                type: Boolean,
                default: false
            }
        },
        computed: { // 自動計算
            locale_string: function () {
                // 表示は半角スペースをいれて2桁にしている。
                return `${`\u00A0${Number(this.value).toString()}`.slice(-2)}`;
            },
            add_disabled: function () {
                // valueが10以上なら+をボタンをクリック無効にする
                return this.value >= 10;
            },
            sub_disabled: function () {
                // valueが10以上なら−ボタンをクリック無効にする
                return this.value <= 0;
            }
        },
        methods: { //メソッド(イベントなどを渡す関数)
            addValue: function (add) {
                this.value += add;
                // value値が変わったら呼び出し元に反映させるおまじない。
                this.$emit('input', this.value);
            }
        }
    })
</script>
<div id="app">
    <p v-for="(item, index) in items">
        <span>{{ item.callName }}:</span><toggle-button type="number" v-model.number="item.counts" style="display: inline;"></toggle-button><span class="subtotal"> {{ subtotalMoney[index] }} 円</span>
    </p>
    <p>
        <span>合計: {{ totalMoney }} </span>
    </p>
</div>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            items: [
                {callName: '1円', unit: 1, counts: 0},
                {callName: '5円', unit: 5, counts: 0},
                {callName: '10円', unit: 10, counts: 0},
                {callName: '50円', unit: 50, counts: 0},
                {callName: '100円', unit: 100, counts: 0},
                {callName: '500円', unit: 500, counts: 0,},
                {callName: '千円', unit: 1000, counts: 0},
                {callName: '弐千円', unit: 2000, counts: 0},
                {callName: '五千円', unit: 5000, counts: 0},
                {callName: '壱万円', unit: 10000, counts: 0}
            ]
        },
        computed: {
            totalMoney: function () {
                let total = 0;
                for (let i = 0; i < this.items.length; i++) {
                    total += this.items[i].unit * this.items[i].counts;
                }
                return Number(total).toLocaleString();
            },
            subtotalMoney: function () {
                let subtotals = [];
                for (let i = 0; i < this.items.length; i++) {
                    subtotals.push(Number(this.items[i].unit * this.items[i].counts).toLocaleString());
                }
                return subtotals;
            }
        }
    });
</script>
</body>
</html>

 お世辞にも綺麗とはいいがたいですが、こんな感じで部品が作れます。本当は.vueファイルにまとめた方が良いのですが、レンタルサーバだとうまくいかないことがあるのでそのままscriptタグでくくって書いています。

あとは想像力

 コンポーネント作りにハマるとあれもこれも部品化したくなるのですが、見た目を良くするならBootstrap とか使うといろいろ捗ると思います。

参考

 Vue.js コンポーネントの基本: https://jp.vuejs.org/v2/guide/components.html
 

9
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
14