【Vue】 関数で生成したhtml内の v-on:clickが機能しない
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 3,756
【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ページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
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つ作成
}
})
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.36%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2019/03/11 02:39
配列で管理するようにすると、上手く動きました。
DOM操作でデータ取得する必要が無いのがVue.jsのメリットなんですね。