Lv1プログラマの誰得メモ

総務女子の趣味とか勉強に関係することのメモ

Vue.jsでカレンダーを作りたい人生だった

Vue.jsでカレンダーを作りたい人生だった(そうでもない)
調べてもPHPで作ってたり、そもそも私が求める以上の挙動をするものが出てきたので、諦めました。 ちょいちょい処理を端折ってるのでコピペだと上手くいかないと思います。
v-forの入れ子とか、二次元配列の出し方とか、その辺を知りたかった。

HTML
<div>
    <table>
        <thead>
            <tr>
                <th></th>
                <th></th>
                <th></th>
                <th></th>
                <th></th>
                <th></th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            <tr v-for='week in calendar'>
                <td v-for='date in week'>
                    <span v-bind:class="date[1]">{{date[0]}}</span>
                </td>
            </tr>
        </tbody>
    </table>
 </div>
javascript
data: function () {
        return {
            calendar: []
        };
},
mounted: function () {
        this.processLoad();
    },
methods: {
        processLoad: function () {
            //カレンダーを作成する
            this.createCalendar(new Date());
        },
        //カレンダーの作成
       createCalendar: function (date) {
            var startDate = date;
            var currentMonth = date.getMonth();
            //カレンダーの最初の日付を取得
            startDate.setDate(1);
            startDate.setDate(startDate.getDate() - startDate.getDay());
            var calendar = [];

            do {
                var week = [];

                for (var d = 0; d < 7; d++) {
                    var day = [];
                    
                    //1日 もしくは カレンダーのはじめ はMM/DD表示にする
                    if (date.getDate() === 1 ||
                            (d === 0 && calendar.length === 0)) {
                        var month = date.getMonth() + 1;
                        day[0] = month + '/' + date.getDate();

                    } else {
                        day[0] = date.getDate();
                    }
                    //今日の日付は表示を変える
                    if (this.compareYMD(date, new Date())) {
                        day[1] = 'current';
                    } else {

                        day[1] = 'others';
                    }
                    week.push(day);
                    date.setDate(date.getDate() + 1);
                }
                calendar.push(week);
            } while (date.getMonth() === currentMonth)
            {

            }
            this.calendar = calendar;
        }
}


曜日もHTMLべた書きじゃなくて配列にすればよかったけど割愛。
compareYMD()関数は書き忘れたのではありません、コードが長くなるなと思ったので省略したのです。決して、決して、力尽きたのではありません。信じてください。(2つの引数(年月日)を比較して同じだったらtrueを返す関数です)

完成図

CSSとかちょこちょこっと良い感じに直したらこんな感じになります。bootstrapは便利だナァ。 f:id:megsan:20200123133353p:plain

getMonth()がやっかいだった

Date型のgetMonth()(日付オブジェクトから月を取得する)がやっかいで、取得した月は0から始まる。つまり、12月は「11」という値を、1月は「0」という値を取得する。なので、「2020年1月31日」という日付オブジェクトから「1月」を取り出す際は、「obj.getMonth()+1」という書き方をしないといけない。こんにゃろ!
そのくせ、new Date() でオブジェクトを作成するときは「new Date(2020, 1, 31)」という書き方をする。そこは「1」でいいんかい!
おそらく月に関しては数字より英語表記のJanuary, February, ... December が一般的だから、getMonth()で取得する値はあくまで月が格納された配列のindexって感じなんだろうな。getDay()で取得する曜日も 0, 1, 2 ... 6 といった数字だし。(日曜が0、月曜が1、土曜が6)たしかに月曜日のこと「1曜日」って言わないわ。