Make it to make it

いろいろ作ってアウトプットするブログ

Vueのdata, computed, methods, watch, filters全部入りでお買い物リスト

たまに見返したいので。dark.min.cssは下記のものを使用。

github.com

tobuy.vue

<template>
  <div>
    <h1>Vue tobuy list</h1>
    <form @submit.prevent="addItem" autocomplete="off">
      <input type="text" v-model="itemToAdd" @keypress.enter="addItem" />
      <button>{{ buttonText }}</button>
    </form>
    <ul class="todo" style="list-style: none; padding-left: 0;">
      <li v-for="(item, index) in items" :key="index">
        <label>
          <button @click="deleteItem(index)">&times;</button>
          <span style="margin-right: 10px;">{{ item.text | capitalize }}</span>
          <button @click="decrease(index)">&minus;</button>
          <span style="margin-right: 6px;">{{ item.quantity }}</span>
          <button @click="increase(index)">&plus;</button>
        </label>
      </li>
    </ul>
    <div v-if="itemTotalAmount > 0">Total items in cart: {{ itemTotalAmount }}</div>
    <div v-else>There is no items!</div>
  </div>
</template>

<script>
import "./dark.min.css";
import _ from "lodash";

export default {
  data() {
    return {
      itemToAdd: "",
      buttonText: "Add item",
      items: [
        { text: "apple", quantity: 1 },
        { text: "banana", quantity: 1 },
        { text: "clementine", quantity: 1 }
      ]
    };
  },
  computed: {
    itemTotalAmount() {
      return this.items.reduce((prev, curr) => prev + curr.quantity, 0);
    }
  },
  methods: {
    addItem() {
      const itemToAdd = this.itemToAdd.toLowerCase();
      const matchedItemIndex = this.items.findIndex(
        item => item.text.toLowerCase() === itemToAdd
      );
      if (matchedItemIndex !== -1) {
        this.items[matchedItemIndex].quantity += 1;
        return;
      }
      this.items.push({ text: itemToAdd, quantity: 0 });
    },
    deleteItem(index) {
      this.items.splice(index, 1);
    },
    increase(index) {
      this.items[index].quantity += 1;
    },
    decrease(index) {
      if (this.items[index].quantity === 1) {
        this.deleteItem(index);
        return;
      }
      this.items[index].quantity -= 1;
    }
  },
  watch: {
    itemToAdd: _.debounce(function() {
      this.buttonText =
        this.itemToAdd !== "" ? `Add ${this.itemToAdd}` : "Add item";
    }, 100)
  },
  filters: {
    capitalize(value) {
      if (!value) return "";
      const newValue = value.toString();
      return newValue.charAt(0).toUpperCase() + newValue.slice(1);
    }
  }
};
</script>