1
3

More than 3 years have passed since last update.

Vue.jsでのボタン制御の方法

Posted at

はじめに

これはVue.jsに触り始めて間もない私が、自分で書いたコードを公式ドキュメントを参考に修正するといった内容になります。
そのため、私と同じようにVue.jsに触り始めた方の参考になれば幸いです。

具体的な内容

先日Vue.js+firebaseでSPAを作成したのですが、Vueを学び始めて数日だったので、ボタン制御の部分で誤った実装をしてしまっていました。
その時はこれでいいやで済ませたのですが、公式ガイドを読んでいる際に正しい実装方法が載っていたので、これをもとにコードを修正しようと思います。

動作のイメージ

動作イメージ.gif

今回の対象は入力フォームに何も入力されていなかった場合にボタンが非活性になるという単純なものです。

元のコード

before.vue
<template>
  <div class="create">
    <div style="margin-right: 50px;text-align: right;">
      <header>NumG</header>
      <router-link to="/">Home</router-link>
    </div>
    <h1>Create</h1>
    <div>
      <p>
        <br />伝えたい言葉を入力してください。
        <br />※個人情報などは入力しないでください。
      </p>
    </div>
    <div>
      <form @submit="checkForm">
        <textarea cols="30" rows="5" :value="message" @input="doUpdate">いつもありがとう!
これからもよろしくね!</textarea>
      </form>
    </div>
    <div>
      <router-link
        id="confirmBtn"
        to="/Confirm"
        tag="button"
        class="btn btn-outline-primary"
      >Confirm</router-link>
    </div>
  </div>
</template>

<script>
export default {
  name: "Create",
  computed: {
    message() {
      return this.$store.getters.message;
    }
  },
  watch: {
    message: function() {
      let el = document.getElementById("confirmBtn");
      if (this.message.length) {
        el.removeAttribute("disabled", "disabled");
      } else {
        el.setAttribute("disabled", "disabled");
      }
    }
  },
  methods: {
    doUpdate(event) {
      this.$store.dispatch("doUpdate", event.target.value);
    },
    checkForm() {
      if (this.message) {
        return true;
      }
      this.error = null;
      if (!this.message) {
        this.error = "伝えたい言葉を入力してください";
      }
      event.preventDefault();
    }
  }
};
</script>

元のコードではrouter-link(送信ボタン)に属性disabledをつけるためにwatchを使い、message(入力値)が変更になるたびに直接DOMの操作を行っていました。あまりVueっぽくない書き方だなぁと思いつつも他に書き方が分からず、時間もないためスルーしてしまいました。
ちなみにmethodsのcheckFormは消し忘れた不要なコードです。。。
上記のwatchのおかげで入力値がない時はそもそもボタンが非活性となるため、ボタンが押せずイベントが発火しません。

ドキュメントの該当箇所

ドキュメントの該当箇所はテンプレート構文#属性の部分です。

<button v-bind:disabled="isButtonDisabled">Button</button>

isButtonDisablednullundefined、またはfalseの値を持つ場合、disabled属性は描画された<button>要素に含められません。

つまり、v-bindを使えばisButtonDisabledの属性を自動で制御(付けたり外したり)できるということです。

修正したコード

before.vue
<template>
  <div class="create">
    <div style="margin-right: 50px;text-align: right;">
      <header>NumG</header>
      <router-link to="/">Home</router-link>
    </div>
    <h1>Create</h1>
    <div>
      <p>
        <br />伝えたい言葉を入力してください。
        <br />※個人情報などは入力しないでください。
      </p>
    </div>
    <div>
      <form>
        <textarea cols="30" rows="5" :value="message" @input="doUpdate"></textarea>
      </form>
    </div>
    <div>
      <router-link
        to="/Confirm"
        tag="button"
        class="btn btn-outline-primary"
        :disabled="isButtonDisabled"
      >Confirm</router-link>
    </div>
  </div>
</template>

<script>
export default {
  name: "Create",
  computed: {
    message() {
      return this.$store.getters.message;
    },
    isButtonDisabled() {
      return this.$store.getters.message.length <= 0;
    }
  },
  methods: {
    doUpdate(event) {
      this.$store.dispatch("doUpdate", event.target.value);
    }
  }
};
</script>

以下のように修正しました。
computedにボタンの押下可否を判定するための算出プロパティisButtonDisabled()を追加
 ※入力値の文字数が0以下の場合にtrue(押下不可)を返すようになっています。
router-link:disabled="isButtonDisabled"を追加
 ※念のため補足ですが:v-bind:を省略した記法です。
不要になったwatchの削除
その他の不要庵部分の削除(form@submit="checkForm"textareaの無駄な例router-linkの使わなくなったidmethodscheckForm())



修正前と比較するとscriptタグの中がかなりすっきりしたてVueっぽくなったと思います!
特にDOMの要素を直接操作する処理が消えたのが大きいかなと思います。
※動作自体は修正前と変わらないので割愛します。

まとめ

公式のドキュメントはちゃんと目を通した方がいいことが分かったので、時間を作って一通り目を通したいと思います。
もっといい書き方があればコメントいただければ幸いです。

1
3
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
1
3