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

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

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

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

JavaScript

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

Q&A

解決済

2回答

11173閲覧

【Vue】vueのコンポーネントから別のコンポーネントを呼び出したい

hasshy

総合スコア102

Vue.js

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

JavaScript

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

0グッド

0クリップ

投稿2018/10/29 10:13

編集2018/10/29 10:44

親子関係があるコンポーネント間の操作についてお伺いしたい事がございます。

お聞きしたい事

2点質問があります。
1点目は解決しました。
スペルミスで、componentsとするところをcomponentとしていました。

質問内に、vue名が直接出ておりますが、その内容は、ソースの構成をご確認ください。

1点目:vueコンポーネントの中から、別のコンポーネントを呼び出せない。 解決しました。

~~ 親子関係があるコンポーネントで、子コンポーネントを呼び出す事ができません。

ソースは後述しますが、mainvisualと言う親コンポーネントから、子コンポーネントである、opning,scene,shearという複数のvueを呼び出したいのですが、
次のようなエラーが表示されます。 ~~

Unknown custom element: <opning> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

~~ export defaultで、対象のコンポーネントを指定していますし、nameオプションも指定しています。 ~~

2点目:コンポーネントの出し分け

vueの開発手法的な話になってしまうのですが、場面ごとにコンポーネントを切り替えるにはどのように実装すれば良いのでしょうか?

例えば、opning.vueと言うコンポーネントは、youtubeの動画を流し、終わったら、scene.vueへ移行するとします。
その場合、opning.vueのdisplayをnoneにし、代わりにscene.vueのdisplayをblockにします。

このような実装方法になると思うのですが、この方法がvueとしてベターな実装方法でしょうか?
(状況の把握ようにvuexも導入する準備はできているのですが、まだ使い方が把握でていません。)

ソース

上記、質問にも出てきた、コンポーネント名も踏まえて説明いたします。

構成

構成は下記です。

component/ mainvisual.vue opning.vue scene.vue share.vue app.js index.html

画面の切り替え的に、3部構成になっていて、それぞれ次のようなコンポーネント構成担っています。

  • opning.vue:初回読み込み時に表示させる要素
  • scene.vue:スライドショーのように次々画面が変わる
  • share.vue:scene.vueで選択した要素に紐づいた要素表示。

mainvisualコンポーネントは、それぞれのコンポーネントの出し分けをする想定です。

index.html

html

1<!DOCTYPE html> 2<html lang="jp" dir="ltr"> 3 <head> 4 <meta charset="utf-8"> 5 <title></title> 6 <!--[if IE]> 7 <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> 8 <![endif]--> 9 </head> 10 <body> 11 <h1>vueテスト</h1> 12 <div id="app"></div> 13 <script src="bundle.js"></script> 14 </body> 15</html>

app.js

js

1import Vue from 'vue' 2import Vuex from 'vuex' 3 4import Cookies from 'js-cookie' 5import axios from 'axios' 6 7import MainVisual from './components/mainvisual' 8 9const URL_BASE = 'http://localhost:3000/' 10 11var mv = new Vue({ 12 el: '#app', 13 data: { 14 scenes_list: [] 15 }, 16 components: { 17 'mainvisual': MainVisual, 18 }, 19 methods: { 20 get_ajax(url, name) { 21 return axios.get(URL_BASE + url) 22 .then((res) => { 23 Vue.set(this, name, res.data); 24 this.$emit('GET_AJAX_COMPLETE'); 25 }) 26 }, 27 get_data(name) { 28 return this.$data[name]; 29 } 30 }, 31 template: '<mainvisual></mainvisual>' 32}); 33 34// クッキーの情報を取得 35Cookies.set('opning-skip', '1');

commponent/mainvisual.vue

これが大元のvueになります。
もしかしたら、app.jsの二度手間かなと思ったのですが、分けています。

現在はtemplate内に全て出力してしまっていますが、本来は状況に応じてコンポーネントを消したり、表示したりしたいと考えています。

vue

1<template> 2<div> 3 <Opning></Opning> 4 <Scene></Scene> 5 <Share></Share> 6</template> 7 8<script> 9import Opning from './opning' 10import Scene from './scene' 11import Share from './share' 12 13export default { 14 component: { 15 'opning': Opning, 16 'scene': Scene, 17 'share': Share 18 } 19} 20</script>

component/opning.vue

オープニング用のコンポーネントです。

vue

1<template> 2<div id="opning"></div> 3</template> 4 5<script> 6import Cookies from 'js-cookie'; 7 8export default { 9 name: 'opning' 10}

component/scene.vue

シーン用のコンポーネントです。

vue

1<template> 2<div id="scene"></div> 3</template> 4 5<script> 6export default { 7 name: 'scene' 8}

component/share.vue

シェア用のコンポーネントです。

vue

1<template> 2<div id="scene"></div> 3</template> 4 5<script> 6export default { 7 name: 'share' 8}

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

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

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

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

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

guest

回答2

0

ベストアンサー

質問2についてです。

Vue.jsには、親子コンポーネント間のやりとりの方法として、以下を用意しています。

  1. 親から子へプロパティの受け渡し
  2. 子から親へイベントの送出(通知)

hasshyさんのケースでは、全体の処理として以下のようにすればいいと思います。

  1. opningコンポーネントで動画が再生される
  2. 動画終了時、opningコンポーネントがvideoendedイベント(名前は任意)を送出
  3. mainvisualコンポーネントがvideoendedイベントを検知
  4. mainvisualコンポーネントで表示する子コンポーネントのフラグを変更
  5. mainvisualコンポーネントフラグに基づき、v-ifでコンポーネントの表示が切り替わる

components/mainvisual.vue

Vue

1<template> 2<div> 3 <Opning 4 v-if="currentContents === 'opning'" 5 v-on:videoended="toggleContents('scene')" 6 ></Opning> 7 <Scene v-else-if="currentContents === 'scene'"></Scene> 8 <Share v-else-if="currentContents === 'share'"></Share> 9</div> <!-- 閉じタグが抜けているので追記 --> 10</template> 11 12<script> 13... 14export default { 15 ... 16 data() { 17 return { 18 currentContents: 'opning' // 初期コンテンツ名 19 } 20 }, 21 methods: { 22 toggleContents(name) { 23 this.currentContents = name 24 } 25 } 26} 27</script>

components/scene.vue

HTMLに動画部分がないので便宜的なものですが、
動画要素終了のイベントを監視し、親コンポーネントにイベントを送出しています。
$emit(this.$emit)は、Vueが自動生成するプロパティで、親にイベントを送出します。

Vue

1<template> 2 <div id="scene"> 3 <video v-on:ended="$emit('videoended')"></video> 4 </div> 5</template> 6 7<script> 8export default { 9 name: 'scene', 10 ... 11}

sceneコンポーネントからshareコンポーネントへの切り替えも、同じように考えてやってみてください。

補足

Vue.jsにおけるイベント処理については、このあたりを読んでみてください。
関連するAPIもチェックするといいと思います。

いくらか開発してみたタイミングで、公式サイトのガイドをあらためて通読されることをおすすめします。

蛇足

opningが「オープニング」のことならopeningでは?

投稿2018/11/11 16:33

NozomuIkuta

総合スコア1260

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

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

hasshy

2018/11/15 07:23

いつもありがとうございます! ご確認が遅れてしまい大変申し訳ございません。 また、稚拙なエラーコードを書いてしまい失礼しました…スペルミスでした。 コードやドキュメントもご用意いただきありがとうございます。 参考にさせていただきます。
NozomuIkuta

2018/11/16 15:05

解決したようでよかったです。 ちなみに、変数名は一文字の場合もあるので、RerefenceErrorにならない限り「間違い(エラー)」では無いですよ。
guest

0

######質問1
components とすべきところが、sが抜けて、componentになっているとか?

javascript

1 2export default { 3 // component: { // sが抜けてる 4 components: { 5 'opning': Opning, 6 'scene': Scene, 7 'share': Share

######質問2
これはちゃんとしたVue.js使いに聞いたほうがいいと思うのですが、思いついたのでついでに回答を(※無視してくださって結構です)。

vueでない場合について考えてみてはどうでしょうか。
イメージとしては、カルーセルに近いような印象を受けます。
カルーセルでいいならカルーセルでいいでしょうが、単に要素の置き換えであれば、置き換えでよいのではないかと?
子のコンポーネントから親に動画終了の通知を出し(もしくはコールバックができればそれでも)、それを受けた親が子供を削除して、次の子供を配置する…とか。

投稿2018/10/29 10:36

編集2018/10/29 10:45
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

hasshy

2018/10/29 10:39 編集

度々ありがとうございます。 1点目はその通りでした。 質問してから、ちょっと間を置いて見直して発覚しました…
退会済みユーザー

退会済みユーザー

2018/10/29 10:46

なるほど笑 とりあえずそれについては解決したみたいでよかったです。 私も質問2については興味がありますので、他の方の回答を楽しみにさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問