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

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

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

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

Q&A

解決済

2回答

9837閲覧

Vueで親から子に関数を渡す方法

SystemAjisai

総合スコア171

Vue.js

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

0グッド

2クリップ

投稿2017/11/30 00:50

###前提・実現したいこと
Vue.jsで自作した子コンポーネントを親から複数箇所で呼び出しています。
そのうちの1つでだけ値の入力後に独自の処理を行いたいため、
親から子に対してコールバック関数を渡したいです。

コンポーネントの中身はテキストボックスにコードを入れると名称を取得してきて隣に表示するというものです。
コールバックで行いたいのは、名称以外の値も一緒に変更するという処理です。
一緒に変更したい値が18個ぐらいあるので、変更したい側に書くよりコード変更時に処理したいと思っています。

Vue.jsのサイトを見るとpropsの型にFunctionが有ったので渡せるのでは?と思っていたのですが、
色々試してみても文字列になってしまいます。
どうやって関数自体を渡せばいいのでしょうか。

###該当のソースコード
※コンポーネントのソースが長いので、関数が渡せるかどうか試しているテストコードを載せています。
子コンポーネント

js

1var child = { 2 props:{ 3 testFnc : Function 4 }, 5 template: "<input type='text' v-on:change='onChange' />", 6 methods:{ 7 onChange:function(){ 8 this.testFnc("aaaa") 9 } 10 } 11}

親側

js

1window.onload = function(){ 2 new Vue({ 3 el:'#vue_contents', 4 methods:{ 5 setTest: function(msg){ 6 alert(msg); 7 } 8 }, 9 components : { 10  'child':child 11 }, 12 }); 13}

呼び出すところ

html

1<child test-fnc="{{setTest}}"></child>

this.testFncに何が入っているかデバッグツールで覗くと「{{setTest}}」が入っています。

###試したこと
1.呼び出しのところにv-bindを付けないと文字列になるという記載を見つけて

html

1<child v-bind:test-fnc="{{setExtendInfo}}"></child>

にしてみました。
結果、ページ全体が表示されなくなりました。

2.関数を変数に入れて変数名を渡してみました。

js

1var test = function(){ 2 alert("呼べてますか…?"); 3}

無駄な抵抗で呼び出し側でもダブルクォーテーションを取ってみる。

html

1<child test-fnc=test></child>

文字列「test」が渡されました…。

3.そもそも親側でwatchしてコールバックを書いてみる
親のデータとバインドしていたので、親側でデータをwatchしてみました。

js

1 watch:{ 2 testdata:function(newVal, oldVal){ 3 alert("ここがコールバックになる予定"); 4 } 5 },

呼ばれることは呼ばれましたが、1文字入力するごとに呼ばれてしまいます。
入力するコードが長さが決まっていないという仕様なので、入力値の長さでチェックすることもできません。

4.3案でフォーカスが当たっている間は処理しないようにしてみる
暫定でコードを入れるテキストボックスにid="testdata"と名付けました。

js

1 watch:{ 2 testdata:function(newVal, oldVal){ 3 if (document.activeElement.id === "testdata") { 4 return; 5 } 6 alert("ここがコールバックになる予定"); 7 } 8 },

alertが呼ばれることはありませんでした。
よく考えたら最後の文字が入力されたときに呼ばれてもフォーカスはまだ当たりっぱなしなので、当たり前でした…。

###補足情報(言語/FW/ツール等のバージョンなど)
言語:Vue.js 2.2.4

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

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

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

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

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

guest

回答2

0

ベストアンサー

ハマリポイントがいくつかありました。

  • 入力を受け付けるイベントはchangeではなくinputです
  • 渡す側(親側)の方では必ずハイフンつなぎで小文字でプロパティを書いてください(Vueが守っているHTMLの仕様)。JSで受け取る側では自動的にキャメルケースに変換されます

ということで動きが検証できたコードは下記になります。

var child = { props: { testFnc: Function }, template: "<input type='text' v-on:input='onChange' />", methods: { onChange: function(ev) { this.testFnc(ev.target.value) } } }; new Vue({ el:'#vue_contents', methods:{ setTest: function(msg){ alert(msg); } }, components : { 'child':child }, });
<div id="vue_contents"> <child :test-fnc="setTest" /> </div>

ただし、子から親へと値を伝達したいということであれば、emitを使うべきです。
あくまでも関数を渡すことは可能だということのみ、示しましたのでご留意ください。

投稿2017/11/30 17:56

編集2017/11/30 18:23
sakapun

総合スコア888

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

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

SystemAjisai

2017/12/01 00:08

無事に動かすことができました! やりたいのは値が変わったら(というか入力し終わったら)なのでon-inputではなくon-changeにしてました。watchで試したようなことを書いたせいだと思います。紛らわしくてすみません。 またご指摘頂いた、「渡す側(親側)の方では必ずハイフンつなぎで小文字でプロパティを書いてください」がどこの事かわかりませんでした…。 propsは「testFnc」で呼び出すところは「test-fnc」にしていたのであっていると思ったのですが…。 関数も渡すならケバブにしないといけないということでしょうか。 動かなかったのは関数名を渡す時に{{}}で囲っていたせいだったんですね。 Vue.jsのver.0.12のページで{{}}で囲って関数を渡していたので、ヴァージョンが上がって何かが変わったんだ!とは思っていたのですが、そこは全く疑っていませんでした。 なんでちょっと取ってみようと思いつかなかったのか…。 子から親に値を伝達したいのではなくて、値を入力し終わったというトリガーを子⇒親に伝達したいという趣旨でした。値は親がバインドしているので、案3,4で書いている通り親側でwatchを書いても発火はできています。しかしその方法だと「入力し終わった」が判断できなくて断念しました。 子側から親のイベントを$emitで発火しなかった理由は、 ・コンポーネント側で独自処理をしたいかどうかを判別する方法 ・他でも独自処理がしたくなった場合、どの独自処理を実行するかを判別する方法 の2つを解決する方法が思いつかず、propsに関数が渡せるようになっていたの、じゃあ渡そうと思った次第です。 質問後にextendsというのでコンポーネントを拡張できるというのに気が付き、独自処理がしたい場合は拡張したコンポーネントを作ればいいじゃない!と思って更なるドツボにはまっていたので回答頂けて本当に助かりました! ありがとうございました!
sakapun

2017/12/01 05:39

ケバブケースにしてましたね(汗)すいません。そこはコピペして動かしてなかったので、私のハマリポイントのようでしたw 解決したようで何よりです^^
guest

0

$emit によるイベント発火でできませんか?

投稿2017/11/30 16:01

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

SystemAjisai

2017/11/30 23:29

ありがとうございます。 根本的に使い方を間違えているのかもしれませんが、本文に記載の通り親側でコンポーネントを複数回呼び出していて、入力後に独自の処理を行いたいのがそのうちの1つだけです。 $emitで発火する場合はコンポーネント側に記載するのだと思うのですが、 ・コンポーネント側で独自処理をしたいを判別する方法 ・他でも独自処理がしたくなった場合、どの独自処理を実行するかを判別する方法 の2つをスマートに解決する方法を思いつかず、propsに関数が渡せるようになってるんだから渡せばいいじゃないという方向に進んでいました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問