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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Vue.js

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

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Q&A

解決済

1回答

689閲覧

vue.js キーボード操作で関数を実行したい

atsuton

総合スコア12

Vue.js

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

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

0グッド

1クリップ

投稿2019/01/26 16:58

Django + Vue.js で、配列の中身を順番に表示させようとしています。

具体的には、
[進む]ボタンをクリックするたびに、配列の1番目、2番目・・・が表示され、
[戻る]ボタンをクリックするたびに、配列の最後から順番に表示が隠れます。

ボタンをクリックした場合には、上記は実現可能です。
キーボードの左右キーを押下した際にも同様になるようにしたいですが、以下の課題があります。

■課題
・一度[進む]ボタンをクリックしないとキーボードの右キー操作が有効にならない。
・左キー操作については反応なし
※console のログを見る限りでは、キーボードを押下はキャッチで来ている模様。

課題の解決策を教えていただけますとありがたいです。

以下、テンプレートに使用している html ファイルです。

html

1{% extends 'base.html' %} 2 3{% block content %} 4 <div class="content" id="content" v-on:keydown.right="showNextContent()"> 5 <button v-on:click="hideLastContent">戻る</button> <button v-on:click="showNextContent()">進む</button> 6 <div v-for="value in object"> 7 <div v-html="value"> 8 [[ value ]] 9 </div> 10 </div> 11 </div> 12{% endblock %} 13 14{% block extrajs %} 15 <script> 16 const contentArray = ("abcdefghij") 17 </script> 18 <script> 19 20 </script> 21 <script> 22 var content = new Vue({ 23 el: '#content', 24 delimiters: ['[[', ']]'], 25 data: { 26 object: [] 27 }, 28 mounted() { 29 window.addEventListener('keydown', function(e){ 30 console.log(e.keyCode) 31 console.log(this.object.length) 32 if (e.keyCode === 39) { 33 this.showNextContent 34 } else if (e.keyCode === 37) { 35 this.hideLastContent 36 } 37 }); 38 }, 39 methods: { 40 showNextContent: function(){ 41 console.log(this.object.length) 42 console.log('show') 43 if (this.object.length < contentArray.length) { 44 this.object.push(contentArray[this.object.length]) 45 } 46 }, 47 hideLastContent: function(){ 48 console.log('hide') 49 if (this.object.length > 0) { 50 this.object.splice(this.object.length-1,1) 51 } 52 }, 53 } 54 }) 55 </script> 56{% endblock %}

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

・一度[進む]ボタンをクリックしないとキーボードの右キー操作が有効にならない。

html

1<div ... v-on:keydown.right="showNextContent()">

ルート要素のdivにフォーカスが当たる事で、v-onのメソッドが動くからです。

・左キー操作については反応なし

javascript

1if (e.keyCode === 39) { 2 this.showNextContent; 3} else if (e.keyCode === 37) { 4 this.hideLastContent; 5}

showNextContent/hideLastContentはメソッドなので()をつけないと実行されません。
this.showNextContent()としてメソッドを実行しましょう。(hideLastContentも同様)
ここの処理さえあれば、ルート要素のv-onの定義は不要になります。

上記で動くようになりますが、コンポーネントが削除されてもwindow.addEventListenerには関数が登録されたままなので、beforeDestroy などで解除する必要があります。

最後に、それらを全てやってくれる、vue-global-eventsというコンポーネントがあるので、これを使ってはどうでしょうか。

追記 window.addEventListenerが正しく動かない理由

addEventListenerの関数内ではthisがwindowもしくはundefinedのどちらかになります。
これはjavascriptのthisの扱いを理解する必要があるのですが、
ここで説明するには長くなりますし、解説しているサイトはたくさんありますので、
そちらを検索して理解してください。

JavaScript の this を理解する多分一番分かりやすい説明を見るとわかりやすいかもしれません

一番簡単ない解決は、以下のようにthisを変数に保存するのが一番簡単です。

javascript

1var self = this; // thisを変数に保存 2window.addEventListener('keydown', function(e){ 3 self.showNextContent(); // 保存したselfで関数を実行 4});

投稿2019/01/27 01:24

編集2019/01/27 09:06
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

atsuton

2019/01/27 08:51

ご回答ありがとうございます! html の content に左キー 押下時の関数を指定していないことに気が付き、追加しました。 v-on:keydown.left="hideLastContent()" javascript にも this.showNextContent(), this.hideLastContent() というように括弧を追加しました。 その上で、content 内の v-on:keydown.right="showNextContent()" 及び v-on:keydown.left="hideLastContent()" を消すと、javascript 内の this.showNextContent(), this.hideLastContent() は実行されないようでした。 vue-global-events のご紹介ありがとうございます。 git の使い方を把握していないので、試してみます。
退会済みユーザー

退会済みユーザー

2019/01/27 09:07

thisの問題だと思いますので、追記しました。
atsuton

2019/01/27 09:24

ありがとうございました! 無事実行できるようになりました。 This の扱いに関するサイトのご紹介もありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問