###前提・実現したいこと
勉強のためVue.jsでコードを入力したらAjaxで名称を取得し、名称フィールドに表示するコンポーネントを作りました。
名称を取得する処理はv-on:change="onChange()"
で設定し、想定通りの挙動が実現できています。
しかし、実際の社内システムで使うと想定した場合、コード入力を音声でもできないといけません。
音声認識終了の関数(JavaScript)からコードをセットすることになるため、「値が変わった」という判定が行われず、名称取得のイベントが動いてくれません。
現状は、音声認識終了の関数の最後で、
javascript
1$('コードを入力するフィールド').trigger('change');
のようにしてchangeイベントを発火させていますが、
Vue.jsのコンポーネントでは、コードを入力するインプットタグにonchangeイベントが設定されているわけではないので、同じようにやっても名称を取得する処理が動いてくれません。
Vue.jsのインスタンス?の外の、全く関係ないJavaScript関数からv-on:changeで設定したイベントを動かすことはできないのでしょうか?
###該当のソースコード
動作確認は音声認識を使わず「Scriptで値をセットしたらonchangeイベントが動かない」に絞って行っています。
以下は動作確認用のソースです。
javascript
1// ↓値を変える関数(テスト用) 2function changeTest(){ 3 $('コードを入力するフィールド').val('存在するコード').trigger('change'); 4} 5 6// ↓Vueのコンポーネント 7Vue.component('test-codename', { 8 props: { 9 codeId: String, 10 nameId: String, 11 }, 12 template: '<input type="text" ' 13 + 'ref="codesearch" ' 14 + ':name="this.codeId" ' 15 + ':id="this.codeId" ' 16 + 'v-on:input="$emit(\'input\', $event.target.value)"' 17 + 'v-on:change="onChange() >"', 18 methods: { 19 onChange: function(){ 20 var val = this.$refs.codesearch.value; 21 var jqXHR = $.ajax({ 22 type: 'GET', 23 url: (名称取得のurl), 24 dataType: 'json' 25 }); 26 var setId = this.nameId; 27 jqXHR .done(function(data){ 28 if(data == null){ 29 $("#"+setId).val(""); 30 return; 31 } 32 $("#"+setId).val(data["名称"]); 33 }); 34 } 35 } 36})
###試したこと
■trigger('change')でイベント発火を試みる
GoogleChromeでF12を押したら出てくるツールでコード入力フィールドを確認したら
そもそもonchangeイベントが振られてないので、この方法では発火しませんでした。
■watchを使ってみる
watchも値の変更を監視するとあったので試してみましたが、
やはりscriptから値を入れた時だけ名称取得のイベントが走りませんでした。
■参照を使ってみる?
該当ソースコードの通りコード入力フィールドをref="codesearch"
としているので
これ越しにchangeが発火できないか試してみました。
vueをnewしてるところで
```javascript
var test = new Vue({
el:'#xxxx',
data:{省略},
})
として、changeTestの中で ```javascript function changeTest(){ // アクセスできるか試してみる alert(test.$refs.codesearch.value); }
としてみました。
中身を見てみたら$refsはオブジェクトとなっていましたが、codesearchはundefinedになってしまいました。
###補足情報(言語/FW/ツール等のバージョンなど)
Vue.js 2.2.4
###追記:解決しました
mio-cさんの回答から、もう1回音声入力の結果をVueで受け取る方法を考え直してみてうまく実装することができました!
質問のタイトルとは方法になるので、解決方法を記載しておきます。
javascript
1window.SpeechRecognition = window.SpeechRecognition || webkitSpeechRecognition; 2// ↓音声入力APIのインスタンスを入れる変数 3var rec = null; 4 5//コードが変わったときの処理はVueの外に出す↓ 6var codeChange = function(val, setId, url){ 7 if(val==""){ 8 $("#"+setId).val(""); 9 return; 10 } 11 var json = ajax_json(url, val); 12 json.done(function(data){ 13 if(data == null){ 14 $("#"+setId).val(""); 15 return; 16 } 17 $("#"+setId).val(data["名称"]); 18});
コンポーネントのテンプレートの中に、マイクを起動するリンクも入れてしまってクリックした時の処理をコンポーネントのmethodsの中に移動させました。
javascript
1methods:{ 2 onChange: function(){ 3 var val = this.$refs.codesearch.value; 4 codeChange (val, this.nameId, this.url); 5 }, 6 onMicStart: function(){ 7 var setId = this.nameId; 8 var url = this.url; 9 if(rec === null){ 10 // 音声入力のAPI 11 rec = new webkitSpeechRecognition(); 12 : 13 : 14 } 15 // 音声入力が終わったときの処理はonresultに入れる 16 // Vueの中でセットしてもちゃんと動いた 17 rec.onresult = function(event){ 18 var val = event.results[0][0].transcript; 19 codeChange (val, setId, url); 20 } 21 rec.start(); 22 }
やってみれば単純だったのですが、既存の処理をそのまま使おうとしすぎて思いつきませんでした。。。
ありがとうございました!!
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/10/12 00:23 編集
2017/10/12 04:44
2017/10/12 04:55
2017/10/12 07:04