質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.49%

  • Vue.js

    1398questions

    Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

【Vue】 関数で生成したhtml内の v-on:clickが機能しない

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 107

nommy

score 1

【Vue】 関数で生成したhtml内のv-on:clickが機能しない

Vue.js初心者です。

以下のコードは、新規追加ボタンでテキストエリアと削除ボタンを生成するプログラムなのですが、<button v-on:click='add'>をクリックしてaddメソッドを実行したときに生成されるhtmlの、削除ボタンのv-on:click='del'が機能しません。(削除ボタンを押しても何の反応もありません。)
デベロッパツールで見ても、<button v-on:click="del">とそのまま出力されてしまっています。
調べても原因がわからず困っています。

created:の中でも this.add()を実行しているのですが、この場合は、生成されたhtmlのv-on:delが正常に機能しています。(削除ボタンで、その親のsectionが削除されます。)同じメソッドを実行しているはずなのに、何が違うのでしょうか?

宜しくお願い致します。

該当のソースコード

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script><!-- Vue.jsの読み込み -->

<body>
  <div id='app'>      
    <div id='makearea'>
    </div> 
    <button v-on:click='add'>新しいメモ</button> <!-- ※このaddメソッド実行で生成された削除ボタンが効かない -->
  </div>
</body>


<script>

new Vue({
  el: '#app',

  methods: {

    add: function(){ // メモ追加

      var section = document.createElement('section') // メモ1つあたりのブロック

      var textbox = document.createElement('textarea') // 入力欄

      var trash = document.createElement('button') // 削除ボタン
      trash.innerHTML = '削除' 
      trash.setAttribute('v-on:click', 'del') // 削除の為のディレクティブ

      var makearea = document.getElementById('makearea') // メモ作成エリア
      makearea.appendChild(section) // セクション生成
      section.appendChild(textbox) // 入力欄生成
      section.appendChild(trash) // 削除ボタン生成

    },

    del: function(e){ // メモ削除

      var trash = e.target
      var section = trash.parentElement 
      var app = section.parentElement
      app.removeChild(section) 

    }

  },

  created: function(){ // インスタンス生成時

    this.add() // 早速メモを1つ作成  // ※このaddメソッド実行で生成された削除ボタンは機能する

  }

})

</script>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

この方法ではVueテンプレートのコンパイル処理が入らないのでv-on:clickは動きません。
また、Vueを使うにあたってappendChildなどでDOMを直接変更するのは初心者が良くやるアンチパターンです。
Vueを使うメリットが完全になくなります。

では実際どうすれば良いかというと、sectionを配列で管理し、テンプレート側でv-forを使って配列の内容をもとにユーザーインターフェイスを表示してやれば良いのです。

このようにすればテキストエリアに入力された値は配列に格納されているので、「入力された内容をファイルに保存する処理を新たに加えたい」とかなった場合に、テキストエリアの値をDOM操作で取得する必要がなくなります。
データを管理する部分と表示する部分で上手く分離される形になって、色々と簡潔に書けるようになるわけです。

  <div id='app'>      
    <div>
      <section v-for="(section, index) in sectionList" :key="index">
        <textarea v-model="section.value"></textarea>
        <button @click="del(index)">削除</button>
      </section>
    </div> 
    <button v-on:click='add'>新しいメモ</button>
  </div>
new Vue({
  el: '#app',

  data: function() {
    return {
      sectionList: []
    }
  },

  methods: {

    add: function() { // メモ追加
      this.sectionList.push({
        value: ''
      })
    },

    del: function(index) { // メモ削除
      this.sectionList.splice(index, 1)
    }

  },

  created: function(){ // インスタンス生成時
    this.add() // 早速メモを1つ作成
  }
})

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/11 02:39

    なるほど、ありがとうございます!
    配列で管理するようにすると、上手く動きました。

    DOM操作でデータ取得する必要が無いのがVue.jsのメリットなんですね。

    キャンセル

同じタグがついた質問を見る

  • Vue.js

    1398questions

    Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。