jtk

【学習メモ】動かして学ぶ!Vue.js 開発入門 その6

Chapter8 データの変化を監視するとき

01 データを使って別の計算をする:算出プロパティ

マスタッシュタグの中に「JavaScriptの式」を書くのではなく「何を表示するのか」を書くほうがわかりやすくなります。それを「名前」で表したものが「computedオプション(算出プロパティ)です」。

 

データの値を計算して使うときは、computed

金額を入力したら、消費税込みの金額を計算する
<div id="app">
  <!-- 金額を入力したら、消費税込みの金額を計算する -->
  <input v-model.number="price" type="number">
  <p>消費税込みの金額{{ taxIncluded }}円</p>
</div>
new Vue({
  el: "#app",
  data: {
    price: 100
  },
  computed: {
    // price が変わったら消費税込みの金額を算出する
    taxIncluded: function () {
      return this.price * 1.08;
    }
  }
});

結果

f:id:jotaki:20190116114834p:plain

単位と個数を入力したら、税込み金額を計算する
<div id="app">
  <!-- 単位と個数を入力したら、税込み金額を計算する -->
  <input v-model.number="price" type="number"> 円 x
  <input v-model.number="count" type="number"><p>   合計:{{ sum }}円</p>
  <p>税込み合計:{{ taxIncluded }}円</p>
</div>
new Vue({
  el: "#app",
  data: {
    price: 100,
    count: 1
  },
  computed: {
    // price か count が変わったら、合計金額を算出する
    sum: function () {
      return this.price * this.count;
    },
    // price が変わったら消費税込みの金額を算出する
    taxIncluded: function () {
      return this.sum * 1.08;
    }
  }
});

結果

f:id:jotaki:20190116114837p:plain

文章を入力したら、残りの文字数を表示する
<div id="app">
  <!-- 文章を入力したら、残りの文字数を表示する -->
  <p>ご感想は、140文字以内でご入力ください。</p>
  <textarea v-model="myText"></textarea>
  <p v-bind:style="{color:computedColor}">残り{{ remaining }} 文字です。</p>
</div>
new Vue({
  el: "#app",
  data: {
    myText: '今日は、いい天気です。'
  },
  computed: {
    // myText の長さが変わったら、残りの文字数を算出する
    remaining: function () {
      return 140 - this.myText.length;
    },
    // remainingが変わったらcomputedColorを算出する
    computedColor: function () {
      col = "green";
      if (this.remaining < 20) {
        col = "orange";
      }
      if (this.remaining < 1) {
        col = "red";
      }
      return col;
    }
  }
});

結果

f:id:jotaki:20190116114840p:plain

文章を入力すると、その文字を含む項目だけ表示される
<div id="app">
  <!-- 文章を入力すると、その文字を含む項目だけ表示される -->
  <ul>
    <input v-model="findWord">
    <li v-for="item in findItems">{{ item }}</li>
  </ul>
</div>
new Vue({
  el: "#app",
  data: {
    findWord: '',
    items: ['Hanako', 'Ichiro', 'Tomoko']
  },
  computed: {
    // this.findWord が変わったら、その文字が含まれるリストを算出する
    findItems: function () {
      if (this.findWord) {
        return this.items.filter(function (value) {
          return (value.indexOf(this.findWord) > -1);
        }, this);
      } else {
        // this.findWord が空のときは、リストをそのまま返す
        return this.items;
      }
    }
  }
});

結果

f:id:jotaki:20190116115040p:plain

02 データの変化を監視する:監視プロパティ

データや変数の値が変わったときに、何かの処理をするには「watchオプション(監視プロパティ)」を使います。タイマーや、非同期の値など、自動的に変化する値などを監視する場合にも使います。

 

データの変化を監視するときは、watch

入力文字を監視して、禁止文字が入力されたらアラートを出す
<div id="app">
  <!-- 入力文字を監視して、禁止文字が入力されたらアラートを出す -->
  <p>禁止文字は、「{{ forbiddenText }}」</p>
  <textarea v-model="inputText"></textarea>
</div>
new Vue({
  el: "#app",
  data: {
    forbiddenText: 'ダメ',
    inputText: '今日は、天気です。'
  },
  watch: {
    // 入力された文字列を監視する
    inputText: function () {
      var pos = this.inputText.indexOf(this.forbiddenText);
      if (pos >= 0) {
        alert(this.forbiddenText + "は、入力できません。");
        this.inputText = this.inputText.substr(0, pos);
      }
    }
  }
});

結果

f:id:jotaki:20190116115043p:plain

タイマーを作る

watch オプションは「時間を監視する」こともできます。

残りの秒数を監視して表示し、0秒になったらアラートを出す
<div id="app">
  <!-- 残りの秒数を監視して表示し、0秒になったらアラートを出す -->
  <p>あと {{ restSec }}秒</p>
  <button v-on:click="startTimer">START</button>
</div>
new Vue({
  el: "#app",
  data: {
    restSec: 5,
    timerObj: null
  },
  methods: {
    startTimer: function () {
      // 残り5秒
      this.restSec = 5;
      // タイマースタート。1秒(1000ミリ秒)ごとに1秒減らす
      this.timerObj = setInterval(() => {
        this.restSec--;
      }, 1000);
    }
  },
  watch: {
    // 残り秒数を監視する
    restSec: function () {
      // 0秒以下になったらアラート&タイマー停止
      if (this.restSec <= 0) {
        alert('制限時間です。');
        clearInterval(this.timerObj);
      }
    }
  }
});

結果

f:id:jotaki:20190116115049p:plain

数字がくるくるとアニメーションをしながら値が増えるinput要素
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js"></script>
<div id="app">
  <!-- 数字がくるくるとアニメーションをしながら値が増えるinput要素 -->
  <p>値は、{{ animeNumber }}です。</p>
  <input v-model.numebr="myNumber" type="number">
</div>
new Vue({
  el: "#app",
  data: {
    myNumber: 0,
    tweenedNumber: 0
  },
  watch: {
    // myNumber を監視して、もし値が変わったら実行する
    myNumber: function () {
      // data の tweenedNumber のプロパティを1行で myNumber まで増やす
      TweenMax.to(this.$data, 1, { tweenedNumber: this.myNumber });
    }
  },
  computed: {
    // tweenedNumber が変わったら、変化中の animeNumber を算出する
    animeNumber: function () {
      return this.tweenedNumber.toFixed(0);
    }
  }
});

結果

f:id:jotaki:20190116115053p:plain


おさらい

データが変化したら、自動的に再計算するとき

1.HTMLで表示させたいところに「プロパティ名」を指定

<p>{{ taxIncluded }} 円</p>

2.Vueインスタンスの「computed:」に、データが変化したら再計算する計算式を用意します。

computed: {
  taxIncluded: function() {
    return this.price * 1.08;
  }
}

データが変化したら、自動的にメソッドを再実行するとき

1.HTMLのtextarea要素などに、「v-model="メソッド名"」と指定

<textarea v-model="inputText"></textarea>

2.Vueインスタンスの「data:」にそのプロパティを用意し、さらに「watch:」に、そのプロパティが変化したら再実行するメソッドを用意しておく

data: {
  inputText: ""
},
watch: {
  inputText: function() {
    // 再実行メソッド
  }
}