目次
vue3コンポーネントの通信方法まとめ
1. 小道具(父から息子へ)
親コンポーネントは子コンポーネントに値を渡し、子コンポーネントは親コンポーネントから渡されたデータをdefinePropsを通じて取得します。
親コンポーネント
<template>
<Child info="小心" :money="money"></Child>
</template>
<script setup lang="ts">
import Child from "./Child.vue";
import {
ref } from "vue";
let money = ref(10000);
</script>
サブアセンブリ
<template>
<p>{
{
info }}</p>
<p>{
{
money }}</p>
</template>
<script setup lang="ts">
//使用defineProps方法接受父组件传递过来的数据
const props = defineProps(["info", "money"]); //数组写法
// const props = defineProps({ //对象写法
// info: String,
// money: Number,
// });
</script>
- 注:vue2での書き方
//props:['name'] //方式1
//props:{name:String} //方式2
props:{
//方式3
name:{
type:String, //类型
required:true, //必要性
default:'老王' //默认值
}
}
2.送信(息子から父親へ)
子から親への受け渡しはカスタム イベントを通じて実現され、カスタム イベントは子コンポーネントの出力を通じてトリガーされます。
親コンポーネント
<template>
<!-- 绑定自定义事件xxx:实现子组件给父组件传递数据 -->
<Child @xxx="handler"></Child>
</template>
<script setup lang="ts">
import Child from "./Child.vue";
const handler = (param1: any, param2: any) => {
console.log(param1, param2); //小,心
};
</script>
サブアセンブリ
<template>
<button @click="handler">子传父</button>
</template>
<script setup lang="ts">
//利用defineEmits方法返回函数触发自定义事件
let emit = defineEmits(["xxx"]);
const handler = () => {
emit("xxx", "小", "心");
};
</script>
- 注: vue2 での記述方法は、vue インスタンス オブジェクトを通じて直接トリガーされます。
this.$emit('xxx',数据);
3.mittプラグイン(グローバルイベントバス)
任意のコンポーネント通信を実現できるグローバルイベントバス Vue 3ではeventBusが削除されましたが、mittプラグインを使用することで実現可能です。
使い方参考ミット公式サイト
設置
npm install --save mitt
カスタム イベントを配布するには Emit メソッドを使用し
、カスタム イベント リスナーをバインドするには on メソッドを使用します。
- 注: vue2 で書かれています
new Vue({
......
beforeCreate() {
Vue.prototype.$bus = this //安装全局事件总线
},
......
})
this.$bus.$on('xxxx',this.demo) //需要接受数据的组件中给$bus绑定自定义事件
this.$bus.$emit('xxxx',数据) //另一个组件中提供数据
4.v-model(親子コンポーネントデータ同期)
v-modelはフォームデータの双方向バインディングを実現できます。
さらに、v-model は、vue2 の xxxx.sync の糖衣構文に似た、親子コンポーネントのデータ同期も実現できます。
要件: ボタンをクリックすると、親子コンポーネントのデータが同期して変更されます。
- 方法 1: props と Emit を使用して親子コンポーネントの同期を実現する
親コンポーネント: 金額データを子コンポーネントに渡し、カスタム イベント update:modelValue で子コンポーネントによって渡された金額更新データを受け入れます。
子コンポーネント: props を通じて親コンポーネントによって渡されたお金を受け取り、emit を通じてカスタム イベントをトリガーして親コンポーネントのデータを更新します。
- 方法 2: v-model を使用して簡素化する
v-model の本質は、props[modelValue] とカスタム イベント [update:modelValue] を使用することで実現されます。これは、子コンポーネント Child に props[modelValue] を渡し、
開発者ツールから確認できるカスタム イベント update:modelValue をバインドすることと同等で
あり、同時に、親コンポーネントと子コンポーネント間の複数のデータ同期を実現できます。複数の v モデルを使用します。
<!-- 相当于给组件Child传递两个props分别是pageOne与pageTwo,以及绑定两个自定义事件update:pageOne与update:pageTwo实现父子数据同步 -->
<Child v-model:pageOne="msg1" v-model:pageTwo="msg2"></Child>
補足: elementPlus のページネーションも v-model を使用します。
- 注: vue2での .async の使用法
:money.async は、文字列 props[money] を子コンポーネントに渡し、カスタム イベント (update:money) を現在の子コンポーネントにバインドする親コンポーネントを表します。
<template>
<Money :money.sync="money"/>
<!--等价于 -->
<Money :money="money" @update:money="money=$event">
</template>
5.useAttrs(父传子)
Vue3 では、useAttrsメソッドを使用して、親コンポーネントの属性とイベント (ネイティブ DOM イベントやカスタム イベントを含む) を取得できます。props と同様に、親コンポーネントによって渡されるプロパティとプロパティ値を受け入れることができます。
ケース: el-button を使用してコンポーネントをカプセル化し、プロンプト機能を持たせるようにします。
親コンポーネント 子
コンポーネントメソッド
を通じてuseAttrs
コンポーネントのプロパティとイベントを取得します。
また、 el-button での書き込み方法も使えますtype=”$attrs.type“ size="$attrs.size"......
が、これは面倒なので、渡した属性名がバインドされたタグの属性名と一致する場合は、 = "$attrs" の形式を直接使用します。
<template>
<div :title="title">
<el-button :="$attrs"></el-button>
</div>
</template>
<script setup lang="ts">
//引入useAttrs方法:获取组件标签身上属性与事件
import {
useAttrs } from "vue";
let $attrs = useAttrs();
let props = defineProps(["title"]);
console.log($attrs);
</script>
- 注意点:
defineProps が属性を受け入れる場合、useAttrs メソッドによって返されるオブジェクトには、対応する属性と属性値がありません。ここでは、タイトルは props で受け入れられており、useAttrs メソッドはタイトルを取得できません。
- 注: Vue2 で書かれています:
$attrs
属性と$listeners
$attrs
これは、親コンポーネントによって渡される props データを取得できるコンポーネント$listeners
インスタンスのプロパティであり、親コンポーネントによって子コンポーネントに渡されるカスタム イベントを取得できるコンポーネント インスタンスのプロパティです
。子コンポーネントがpropsを通じて受け取るプロパティ、$attrsプロパティの中では取得できません。
親コンポーネント:
<template>
<ElButton type="success" icon="el-icon-delete" size="mini" title="按钮" @click="handler"/>
</template>
サブアセンブリ
<template>
<a :title="title">
<el-button v-bind="$attrs" v-on="$listeners"></el-button>
</a>
</template>
<script>
export default {
props:['title'],
mounted(){
console.log(this.$attrs);
}
}
</script>
6.ref/$parent (親子コンポーネント通信)
6.1 参照
ref は、要素またはサブコンポーネントの参照を登録するために使用されます。つまり、DOM 要素およびサブコンポーネントのインスタンスを取得できます。
その後、ref を通じて子を親に渡し、子コンポーネントのデータとメソッドを親コンポーネントで使用できます。
- 1. オプション API を使用すると、参照はコンポーネントの this.$refs オブジェクトに登録されます。
<!-- 存储为 this.$refs.p -->
<p ref="p">hello</p>
- 2. 複合 API を使用する場合、参照は名前に一致する ref に保存されます。
通常の DOM 要素で使用される場合、参照は要素自体になります。サブコンポーネントで使用される場合、参照はサブコンポーネントのインスタンスになります。
- 注意点:
vue3 のスクリプト セットアップを使用するコンポーネントはデフォルトで閉じられており、外部からアクセスできません。親コンポーネントが子コンポーネントのデータまたはメソッドを取得したい場合は、 defineExposeを通じて外部に公開する必要があるプロパティを指定する必要があります。子コンポーネント内。
例:
親コンポーネント
子コンポーネント
6.2 $parent
$parent は現在のコンポーネントの親コンポーネントのインスタンスを取得できるため、親コンポーネントのデータとメソッドを子コンポーネントで取得できます。
親コンポーネント。親コンポーネントのデータとメソッドは、defineExpose メソッドを通じて外部に公開する必要があります。
<template>
<Child></Child>
</template>
<script setup lang="ts">
import Child from "./Child.vue";
import {
ref } from "vue";
let yourMoney = ref(666);
let myMoney = ref(10);
defineExpose({
yourMoney,
myMoney,
});
</script>
サブアセンブリ。子コンポーネント内のボタンがクリックされたときに、親コンポーネントのインスタンスを取得します。
<template>
<div class="dau">
<button @click="handler($parent)">点击获取父组件实例</button>
</div>
</template>
<script setup lang="ts">
const handler = ($parent) => {
console.log($parent.yourMoney); //666
console.log($parent.myMoney); //10
};
</script>
- 注: vue2 で書かれています
Vue2 を使用して、$children
現在のコンポーネントのすべてのサブコンポーネントのすべてのインスタンスを取得することもできます。
vue3 では$children
削除され、$refs に置き換えられました。
7.provide/inject (祖先コンポーネントと子孫コンポーネント間の通信)
Vue3 では、provide と inject の 2 つのメソッドが用意されており、レベルの深さに関係なく、API によって親コンポーネントから子孫コンポーネントへのデータ転送を実現できます。
7.1 提供(提供)
Provide は、子孫コンポーネントによって注入できる値を提供するために使用されます。
親コンポーネント
<script setup lang="ts">
import Child from "./Child.vue";
import {
ref, provide } from "vue";
let car = ref("小星星");
//祖先组件给后代组件提供数据
//第一个参数就是提供的数据key
//第二个参数是提供的数据
provide("TOKEN", star);
</script>
7.2 インジェクション(注入)
子孫コンポーネントは、inject メソッドを通じてデータを取得し、キーを通じて保存された値を取得できます。
サブアセンブリ
<template>
<div class="child1">
<h1>孙子组件</h1>
<p>{
{
star }}</p>
<button @click="updateCar">更新数据</button>
</div>
</template>
<script setup lang="ts">
import {
inject } from "vue";
//注入祖先组件提供数据
//需要参数:即为祖先提供数据的key
let star = inject("TOKEN");
console.log(star.value); //小星星
//后代组件可以修改注入的值,祖先组件提供的值也会跟着变
const updateCar = () => {
star.value = "摘下月亮";
};
</script>
</script>
注: 子孫コンポーネントは挿入された値を変更でき、祖先コンポーネントによって提供される値も変更されます。
効果
8. スロット(親子コンポーネント通信)
スロット: デフォルト スロット、名前付きスロット、およびスコープ付きスロットに分かれており、親子コンポーネント通信を実現できます。
8.1 デフォルトのスロット
子コンポーネント内でスロット グローバル コンポーネント タグを使用する
<template>
<div>
<slot></slot>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
</style>
親コンポーネント。Todo はサブコンポーネントであり、二重ラベルの内部書き込み構造がサブコンポーネントに渡されます。
<Todo>
<h1>我是默认插槽填充的结构</h1>
</Todo>
8.2 名前付きスロット
コンポーネント内に名前付きの複数の名前付きスロットを残します。
2 つの名前付きスロットを持つ子コンポーネント
<template>
<div>
<h1>todo</h1>
<slot name="a"></slot>
<slot name="b"></slot>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
</style>
親コンポーネント
親コンポーネントは、構造体を指定された名前付きスロットに内部的に渡します。v-slot:を使用します。これは # に置き換えることができます。
<template>
<div>
<h1>slot</h1>
<Todo>
<template v-slot:a> //可以用#a替换
<div>填入组件A部分的结构</div>
</template>
<template #b>//可以用#b替换
<div>填入组件B部分的结构</div>
</template>
</Todo>
</div>
</template>
<script setup lang="ts">
import Todo from "./Todo.vue";
</script>
<style scoped>
</style>
8.3 スコープ付きスロット
スコープスロット:データを転送できるスロットです。子コンポーネントは親コンポーネントにデータを渡すことができ、親コンポーネントは返されたデータを子コンポーネント内でどのような構造または外観で表示するかを決定できます。
次の例では、親コンポーネントは todos データを子コンポーネントに渡し、子コンポーネントは親コンポーネントの値を受け取り、スコープ スロットを通じてデータを親コンポーネントに送り返し、親コンポーネントはスタイルを設定します。データ。
親コンポーネント 子
コンポーネント
効果
- 注: vue2 の親コンポーネントは、scope 属性値を通じて子コンポーネントのデータを取得します。
<template scope="scopeData">
<ul>
<li v-for="g in scopeData.games" :key="g">{
{g}}</li>
</ul>
</template>
9. pinia/vuex(任意コンポーネント通信)
Vue3 は、2 つの集中管理状態コンテナであるPiniaとVuex4を使用して、任意のコンポーネント通信を実現できます。
- Vuex のコア概念: 状態、突然変異、アクション、ゲッター、モジュール
- Pinia の中心概念: 状態、アクション、ゲッター。突然変異やモジュールはありません。
利用参考:Pinia公式サイト、Vuex公式サイト
- 注: vue2 では Vuex3 が使用されていますが、Ponia も使用できます。