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

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

2回答

4978閲覧

reactでkeyイベントを作成したい

ricy

総合スコア48

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2016/08/23 07:25

1,リスト操作する一番上位のメッセージコンポーネント MessageBox
2.リスト全体のメッセージコンポーネント MessageList
3.リスト1行のメッセージコンポーネント Message
3をループして描画
といった設計で描画しているのですが、

個々のmessageにフォーカスして、矢印キーを使ってメッセージのリスト移動をしたいのですが、
どのようにすればいいかご教示いただけないでしょうか。
javascriptのイベントを使えばよさそうではあるのですが・・・

<html> <head> <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script> <script src="https://fb.me/react-0.13.3.js"></script> <script src="https://fb.me/JSXTransformer-0.13.3.js"></script> </head> <body> <div id="content"> </div> <script type="text/jsx"> var Message = React.createClass({ render: function() { return ( <li> <div className="message"> <img src={this.props.data.message} alt=""></img> </div> </li> ); } }); var MessageList = React.createClass({ render: function() { var resultNodes = this.props.data.map(function (row) { return ( <Message data={row} /> ); }); return ( <ul> {resultNodes} </ul> ); } }); var MessageBox = React.createClass({ // 初期値を設定します getInitialState: function() { return {data: [], page: 1, apiUrl: 'http://api.com/get'}; }, componentDidMount: function() { // ajaxでデータを取得 this.requestData(); }, render: function() { return ( <div className="messageBox"> <MessageList data={this.state.data} /> </div> ); } }); React.render( <MessageBox />, document.getElementById('content') ); </script> </body> </html>

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

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

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

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

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

guest

回答2

0

ベストアンサー

それっぽいものを書いてみました。

コツは、

  • tabIndex="-1"を指定してフォーカス可能にすること
  • MessageListstatefocusIndexというプロパティを持たせて、それに応じてフォーカスするようにしたところ、です。

要素にフォーカスするために、Reactのrefという機能を使って生のDOMを操作しています。これについては、こちらにドキュメントがありますの参考にしてください。

今回の実装ではMessageがクリックされてフォーカスしたときに、フォーカスが移動したことをMessageListに伝えるためにプロパティを介して関数を渡していますが、Fluxなどのイディオムを使うとより綺麗に書くことができると思います。

html

1<!doctype html> 2 3<html> 4 <head> 5 <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script> 6 <script src="https://fb.me/react-0.13.3.js"></script> 7 <script src="https://fb.me/JSXTransformer-0.13.3.js"></script> 8 </head> 9 <body> 10 <div id="content"> 11 </div> 12 <script type="text/jsx">//<![CDATA[[ 13 var Message = React.createClass({ 14 render: function () { 15 var focusFlag = this.props.focus 16 var focus = function (li) { 17 if (li && focusFlag) { 18 li.getDOMNode().focus(); 19 } 20 }; 21 22 return ( 23 <li tabIndex="-1" onClick={this.props.notifyFocus} ref={focus}> 24 <div className="message"> 25 <img src={this.props.data.message} alt=""></img> 26 </div> 27 </li> 28 ); 29 } 30 }); 31 32 var MessageList = React.createClass({ 33 getInitialState: function () { 34 return {focusIndex: -1}; 35 }, 36 37 render: function () { 38 var notifyFocus = function (index) { 39 console.log(`notifyFocus: ${index}`) 40 this.setState({focusIndex: index}); 41 }; 42 var resultNodes = this.props.data.map(function (row, index) { 43 return ( 44 <Message data={row} focus={index == this.state.focusIndex} notifyFocus={notifyFocus.bind(this, index)}/> 45 ); 46 }, this); 47 var onKeyDown = function (event) { 48 if (this.state.focusIndex === -1) return; 49 50 switch (event.keyCode) { 51 case 38: // ↑ 52 this.state.focusIndex -= 1; 53 break; 54 case 40: // ↓ 55 this.state.focusIndex += 1; 56 break; 57 } 58 59 this.setState(this.state); 60 }.bind(this); 61 62 return ( 63 <ul onKeyDown={onKeyDown}> 64 {resultNodes} 65 </ul> 66 ); 67 } 68 }); 69 70 var MessageBox = React.createClass({ 71 // 初期値を設定します 72 getInitialState: function () { 73 return {data: [], page: 1, apiUrl: 'http://api.com/get'}; 74 }, 75 76 componentDidMount: function () { 77 // ajaxでデータを取得 78 this.requestData(); 79 }, 80 81 render: function () { 82 return ( 83 <div className="messageBox"> 84 <MessageList data={this.state.data} /> 85 </div> 86 ); 87 } 88 }); 89 90 React.render( 91 <MessageBox />, 92 document.getElementById('content') 93 ); 94 //]]></script> 95 </body> 96</html>

投稿2016/08/23 08:35

MakeNowJust

総合スコア545

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

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

ricy

2016/08/23 11:59 編集

矢印キーでfocusできました! サンプルコードまで頂いて参考になりました。 一点、そのフォーカスしたリストにてenterkeyをおして、 詳細画面にとびたいのですが、 onKeyDown内にいれる方針でよいでしょうか? この場合、focusされたli要素にもっているid(サンプルではliだけでしたが、実際は<li id=3>といった感じでidを持っている)がとれれば画面詳細がみれそうなのですが、 もしお時間あればアドバイスいただければと思います。 var onKeyDown = function (event) { if (this.state.focusIndex === -1) return; switch (event.keyCode) { case 38: // ↑ this.state.focusIndex -= 1; break; case 40: // ↓ this.state.focusIndex += 1; break; case 13: // ↓ console.log("enter") break; } this.setState(this.state); }.bind(this);
guest

0

どこかのタイミングでリストにフォーカスが当たった状態から処理を開始する想定でしょうか?

onkeydownまたはonkeyupでキーの押下によるイベントを発火させて、
その時押されたキーコードが何番かを判定すると良いと思います。
キーコード一覧
37~40のどれかですね。

押されたキーが上下左右どれなのかによって、フォーカス先を変更すれば良いでしょう。

投稿2016/08/23 08:00

NatsumiOki

総合スコア1298

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

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

ricy

2016/08/23 11:54

リストはデフォルトで一番上にきたものにフォーカスされている設定です、 そのまま下にいければいいなと思い質問させていただきました。前回含めて、回答頂いてありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問