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

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

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

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

JavaScript

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

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

解決済

2回答

1863閲覧

【vue3】【composition api】子要素でdefineExposeで定義した関数が親要素で正常に参照できない

kuchibashi

総合スコア1

Vue.js

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

JavaScript

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

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

1グッド

0クリップ

投稿2023/03/29 06:54

編集2023/03/29 07:03

実現したいこと

親要素にてvfor内の:refを使用して子要素のdefineExposeで定義した関数にアクセスしたい

前提

js

1"vue": "^3.2.13",

下記のようなサイトを作成
イメージ説明

  1. hello world コンポーネントを作成してそれをv-forで表示
  2. さらにそのコンポーネントを:refにて取得した
  3. fireを押下するとdefineExposeで定義した子要素のexposeFunctionを発火させたい

発生している問題・エラーメッセージ

Fire 押下時:refで取得したコンポーネントからexposeFunction

ts

1Uncaught TypeError: componentRef.exposeFunction is not a function 2 at eval (HomeView.vue?71c7:27:1) 3 at Proxy.forEach (<anonymous>) 4 at onFire (HomeView.vue?71c7:26:1) 5 at callWithErrorHandling (runtime-core.esm-bundler.js?d2dd:173:1) 6 at callWithAsyncErrorHandling (runtime-core.esm-bundler.js?d2dd:182:1) 7 at HTMLButtonElement.invoker (runtime-dom.esm-bundler.js?2725:345:1)

該当のソースコード

子要素 HelloWorld.vue

ts

1<template> 2 <div class="hello"> 3 <h1>{{ msg }}</h1> 4 </div> 5</template> 6 7<script setup lang="ts"> 8import { defineProps, defineExpose } from "vue"; 9 10interface Props { 11 msg: string; 12} 13const props = defineProps<Props>(); 14 15function exposeFunction() { 16 console.log(props.msg); 17} 18defineExpose({ 19 exposeFunction, 20}); 21</script> 22 23<!-- Add "scoped" attribute to limit CSS to this component only --> 24<style scoped lang="scss"></style> 25

親要素 HomeView.vue

ts

1<template> 2 <div 3 class="home" 4 v-for="item of items" 5 :key="item.id" 6 :ref="setComponentRefs" 7 > 8 <HelloWorld :msg="item.value" ref="componentRef" /> 9 </div> 10 <button @click="onFire">Fire</button> 11</template> 12 13<script setup lang="ts"> 14import { ref } from "vue"; 15import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src 16 17const componentRefs = ref<Array<InstanceType<typeof HelloWorld>>>([]); 18 19const items = ref([ 20 { id: "001", value: "vue1" }, 21 { id: "002", value: "vue2" }, 22 { id: "003", value: "vue3" }, 23]); 24// eslint-disable-next-line @typescript-eslint/no-explicit-any 25function setComponentRefs(el: any) { 26 if (el) { 27 componentRefs.value.push(el as InstanceType<typeof HelloWorld>); 28 } 29} 30function onFire() { 31 componentRefs.value.forEach((componentRef) => { 32 componentRef.exposeFunction(); 33 }); 34} 35</script> 36

ちなみにvscodeのホバーした際のヒントでは正常に出てくる(型定義が影響しているかも?)
イメージ説明

試したこと

v-forを使用せずに単体コンポーネントのリファレンスのexploreFunctionは正常に発火する

補足情報(FW/ツールのバージョンなど)

該当ソースコードをアップしましたので、再現などにお役立てください
https://github.com/mendakon/defineEmitnotWorked

y-temp4👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

テンプレート参照をv-forの中で使用した場合、自動で要素の配列になります。
https://ja.vuejs.org/guide/essentials/template-refs.html#refs-inside-v-for

そのため、pushで配列を作成する必要はなく、そのままコンポーネントにref属性をつけてあげれば、配列を取得できます。

ts

1<template> 2 <div 3 class="home" 4 v-for="item of items" 5 :key="item.id" 6 > 7 <HelloWorld :msg="item.value" ref="componentRefs" /> 8 </div> 9 <button @click="onFire">Fire</button> 10</template> 11 12<script setup lang="ts"> 13import { ref } from "vue"; 14import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src 15 16const componentRefs = ref<Array<InstanceType<typeof HelloWorld>>>([]); 17 18const items = ref([ 19 { id: "001", value: "vue1" }, 20 { id: "002", value: "vue2" }, 21 { id: "003", value: "vue3" }, 22]); 23 24function onFire() { 25 componentRefs.value.forEach((componentRef) => { 26 componentRef.exposeFunction(); 27 }); 28} 29</script>

投稿2023/04/01 11:12

yukihide1188

総合スコア44

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

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

kuchibashi

2023/04/03 07:36

正常に動作しました。vueの仕様まで教えていただきありがとうございます。
guest

0

以下のような実装は要件を満たさないでしょうか?

html

1<template> 2 <div class="home"> 3 <HelloWorld 4 v-for="item of items" 5 :key="item.id" 6 :msg="item.value" 7 :ref="(el) => setComponentRefs(el)" 8 /> 9 </div> 10 <button @click="onFire">Fire</button> 11</template>

投稿2023/03/31 06:48

y-temp4

総合スコア67

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

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

kuchibashi

2023/04/03 07:37

動作しました。v-forについていろいろと勘違いしていたみたいです。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問