Techvenience

Technology × Convenience - Vue / React / Next / Nuxt / ChatGPTなどのIT技術がもたらす便利さをお伝えします。最近はChatGPTなどのAI技術を使ってブログを書いています。

【Vue.js】Vue.jsとLocalStorageを使って献立管理アプリを作成 登録画面 - Part2 - 【LocalStorage】

【Vue.js】Vue.jsとLocalStorageを使って献立管理アプリを作成 登録画面 - Part2 - 【LocalStorage】

f:id:duo-taro100:20160218004611p:plain

前回
www.sky-limit-future.com

mainComponent.jsの解説 part1

indexComponent

今回はホーム画面から一覧画面にリダイレクトしているので使用していません。

// indexComponent
Vue.component('indexs', {
    template : 
        '<div class="contents">'+
          '<div class="today-menu">'+
            '<h5>今日の献立</h5>'+
          '</div>'+
          '<div class="recent-menu">'+
            '<h5>直近の献立</h5>'+
          '</div>'+
        '</div><!-- .contents -->',
    data: function () {
        return {
            todayMenu : "",
            recentMenu : ""
        }
    },
    methods: {
        
    },
    mounted: function(){
        this.todayMenu
    }
})
準備中画面

今回は準備画面を使用していません。
が、使う場面も出てくるかもしれないので念のため用意しています。

// prepareComponent
Vue.component('prepares', {

    template : 
        '<div class="contents">'+
          '<div class="prepare-box">'+
            '<h1 class="tac">準備中</h1>'+
          '</div>'+
        '</div><!-- .contents -->'
})
登録画面

一覧画面の前に登録画面からです。いくつかに分割して解説します

■html部分

template : 
      '<div class="contents">'+
        '<h5>献立登録</h5>'+
        '<div class="regist-menu">'+  
            '<div class="menu-input-block">'+
                '<p class="labels">献立名</p>'+
                '<input type="text" v-model="menuName">'+
            '</div><!-- .menu-input-block -->'+
            '<div class="menu-input-block">'+
                '<p class="labels">献立のジャンル</p>'+
                '<select v-model="genre">'+
                    '<option v-for="genres in menuGenre">{{genres}}</option>'+
                '</select>'+
            '</div><!-- .menu-input-block -->'+
            '<div class="menu-input-block">'+
                '<p class="labels">献立を使った直近の日付</p>'+
                '<input type="text" v-model="menuDate">'+
            '</div><!-- .menu-input-block -->'+
            '<button class="submit" @click="registMenu()">登録</button>'+
        '</div>'+
      '</div><!-- .contents -->',

「登録用の献立名」、「献立ジャンル」、「献立を使った直近の日付」の入力フォームを用意しました。

■登録用の献立名
ヘッダーメニューの「献立登録」を押下して遷移してきた場合は空文字になるようにしています。
一方で、一覧画面から「編集」ボタンを押下して遷移してきた場合はそのメニューの献立名称が入るようになっています。
登録画面に遷移する時にパラメータとして送る方法は以下の通りです。

{ path: 'regist', query: { keyName: 'test' }

この例だと

/regist?keyName=test

というurlになります。
このkeyNameの受け取り方は

this.$route.query.keyName

となっています。実際のソースは以下の通りです。

data: function () {
        return {
            // パラメータとして受け取った献立のメニュー名を代入します。
            menuName : this.$route.query.keyName,
            menuGenre : [],
            genre : REGIST_MENU_GENRE.MEAT,
            menuDate : ''
        }
    },

■献立ジャンル
data.jsのREGIST_MENU_GENREを表示しています。
ジャンルを増やしたい場合はdata.jsを編集する必要があります。
ジャンルはユーザーが作成・追加できるようにしてもよかったのですが、今回は固定にしました。
今は「肉」、「魚」しかないですが、嫁に聞いた上で増やす予定です。

■献立を使った直近の日付
画面に来た時には当日の日付がyyyyMMddで入るようになっています。

mounted: function(){
    // data.jsのREGIST_MENU_GENREからmenuGenreに移し換えて、献立ジャンルのプルダウンを作成しています。
    for(genre in REGIST_MENU_GENRE) {
        this.menuGenre.push(MENU_GENRE[genre]);
    }

    // 献立を使った直近の日付に当日の日付をyyyyMMddで入れています。
    var now = new Date();
    this.menuDate = now.getFullYear()+
      ( "0"+( now.getMonth()+1 ) ).slice(-2)+
      ( "0"+now.getDate() ).slice(-2);
},

mountedについてはこちら。私の感覚としては画面が出来上がった直後に実施される。

jp.vuejs.org


■登録処理
上記で入力した値のLocalStorageへの登録処理の解説です。
今回は「menuList」というkeyに対して保存していきますが、その実装はstorage.jsに記載があります。
登録処理の中でやっていることは

・バリデーション
・新規登録か更新か
・登録or更新完了後の画面遷移

今回のデータ構造は以下のようにしています。

key : 献立名称
value : {name : 献立名称, genre : 献立ジャンル, date : 献立使用日付の配列, latestDate : 直近に使用した配列}

メソッド名は「registMenu」で登録ボタン押下で動きます。

'<button class="submit" @click="registMenu()">登録</button>'+

実装内容。

methods: {
    registMenu : function() {
        // バリデーション ここから
        // 今回は空文字チェックのみ実施しています。全て同様の実装なので、メソッドを外出しした方がよかったですね。       
        if(this.menuName == '' || this.menuName == undefined || this.menuName == null) {
            alert('献立名を入力して下さい。');
            return;
        }            
        if(this.genre == '' || this.genre == undefined || this.genre == null) {
            alert('ジャンル名を正しく選択して下さい。');
            return;
        }            
        if(this.menuDate == '' || this.menuDate == undefined || this.menuDate == null) {
            alert('日付を入力して下さい。');
            return;
        }

        // 献立名の重複を確認
        // getMenuList()はstorage.js参照
        var menuList = getMenuList();
        var menu = null;
        if(menuList != null) {
            // 一件以上登録されている場合は、献立名に紐づくデータが存在すればそれをmenuに代入する。
            // 存在しなければundefinedになると思います。(確認してないけど)
            menu = menuList[this.menuName];
        } else {
            // 一件も登録がない場合は空オブジェクトを用意します。
            menuList = {};
        }

        // menuがnull or undefined だった場合 => 新規登録
        // menuが存在する場合 => 更新
        if(!menu){
            // 新規登録
            console.log('[START]regist new menu.');
            // this.menuNameというkeyに対してvalueを登録します。
            menuList[this.menuName] = {'name':this.menuName, 'genre':this.genre, 'date':[parseInt(this.menuDate)], 'latestDate':parseInt(this.menuDate)}
            // setMenuList()はstorage.js参照
            setMenuList(menuList);
            alert('献立の登録を行いました。');
            console.log('[END]regist new menu.');
        } else {
            // 更新
            console.log('[START]update new menu.');
            var isUpdate = confirm('献立名:' + this.menuName + 'が既に存在します。更新してもよろしいですか?\n(※)最も新しい日付で表示されます。');
            var dateList = menu['date']
            // 同じ献立名に対して、同じ日付で登録しようとしたらエラーとします。
            for(i in dateList) {
                if(dateList[i] == parseInt(this.menuDate)) {                      
                    alert('既に ' + this.menuDate + ' の日付で ' + this.menuName + ' に登録があります。日付を変えて登録して下さい。');
                    return;
                }
            }

            // 献立を使用した日付のリストに追加
            dateList.push(parseInt(this.menuDate));
            // ソート(日付の新しい順)
            dateList.sort(function(a,b){
                if(a > b) return -1;
                if(a < b) return 1;
                return 0;
            });
            // オブジェクトのdata部分をソートした結果で上書きします。
            menu['date'] = dateList;
            // 最新の日付をkatestDateに上書きします。
            menu['latestDate'] = dateList[0];
            // menuListに上書きします。
            menuList[this.menuName] = menu;
            setMenuList(menuList);
            alert('献立の更新を行いました。');
            console.log('[END]update new menu.');
        }
        // 最後に一覧画面に遷移させます。
        this.$router.push({ path: 'list' })
    }
  },

vue-routerを使用して、プログラム上から画面を変更するには以下のようにします。

this.$router.push({ path: 'list' })

本日はここまでです。
一覧画面の実装については次回。
www.sky-limit-future.com