\n\n\n\n\n```\n\n親要素 HomeView.vue\n```ts\n\n\n\n\n```\nちなみにvscodeのホバーした際のヒントでは正常に出てくる(型定義が影響しているかも?)\n![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2023-03-29/2e4b7067-0de2-4dde-a113-22addde6564d.png)\n\n### 試したこと\nv-forを使用せずに単体コンポーネントのリファレンスのexploreFunctionは正常に発火する\n\n### 補足情報(FW/ツールのバージョンなど)\n該当ソースコードをアップしましたので、再現などにお役立てください\nhttps://github.com/mendakon/defineEmitnotWorked\n","answerCount":2,"upvoteCount":1,"datePublished":"2023-03-29T06:54:30.202Z","dateModified":"2023-04-03T16:37:58.000Z","acceptedAnswer":{"@type":"Answer","text":"テンプレート参照をv-forの中で使用した場合、自動で要素の配列になります。\nhttps://ja.vuejs.org/guide/essentials/template-refs.html#refs-inside-v-for\n\nそのため、```push```で配列を作成する必要はなく、そのままコンポーネントにref属性をつけてあげれば、配列を取得できます。\n\n```ts\n\n\n\n```","dateModified":"2023-04-03T16:35:21.000Z","datePublished":"2023-04-01T11:12:19.819Z","upvoteCount":1,"url":"https://teratail.com/questions/c6w0bpr95gg60r#reply-v1q7sreak5qldx"},"suggestedAnswer":[{"@type":"Answer","text":"以下のような実装は要件を満たさないでしょうか?\n\n```html\n\n```","dateModified":"2023-03-31T06:48:09.085Z","datePublished":"2023-03-31T06:48:09.085Z","upvoteCount":1,"url":"https://teratail.com/questions/c6w0bpr95gg60r#reply-4372zlbpxviegl","comment":[{"@type":"Comment","text":"動作しました。v-forについていろいろと勘違いしていたみたいです。ありがとうございます。","datePublished":"2023-04-03T07:37:58.227Z","dateModified":"2023-04-03T07:37:58.227Z"}]}],"breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"https://teratail.com","name":"トップ"}},{"@type":"ListItem","position":2,"item":{"@id":"https://teratail.com/tags/Vue.js","name":"Vue.jsに関する質問"}},{"@type":"ListItem","position":3,"item":{"@id":"https://teratail.com/questions/c6w0bpr95gg60r","name":"【vue3】【composition api】子要素でdefineExposeで定義した関数が親要素で正常に参照できない"}}]}}}
質問するログイン新規登録

Q&A

解決済

2回答

2992閲覧

【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

1

0

実現したいこと

親要素にて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.29%

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

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

質問する

関連した質問