vue3组件通信(父给子传参,子调用父的方法,父调用子的方法,顶层组件给底层组件传参,底层组件调用顶层组件的方法)

目录

1.父传子(父给子传参)

2.子传父(子调用父的方法)

3.父调用子的方法

4.顶层给底层传参,底层调用顶层的方法

5.模板引用


1.父传子(父给子传参)

①.步骤

父组件中给子组件通过绑定属性的方式传递往子组件的参数

子组件内部通过props选项进行接收

②.示例

父组件:

<script setup>
// 局部组件,导入之后就可以进行使用
import chlid from '@/components/child.vue'
import { ref } from 'vue';
const money = ref(50);
const add = () =>{
  money.value += 10;
}
</script>

<template>
  <div>
    <h3>父组件 {{ money }}
      <!-- 在父组件中改变了往子组件传递的值,子组件会接收到最新的值,并更新视图 -->
    <button @click="add"> 挣钱</button>
  </h3>
  <!-- 给子组件,以添加属性的方式进行传递,可以传递固定值或者动态值-->
    <chlid car = "BYD" :money = "money"></chlid>
  </div>
</template>

子组件:

<template>
<!-- 在模板中可以直接使用参数,不需要通过prop.的方式 -->
<div class="son"> 子组件  {{ car }} - {{ money }} 
<button>花钱</button>
</div>
</template>

<script setup>
const prop = defineProps({
    money:Number,
    car:String
})
const emit = defineEmits(['sub'])
// 在js中需要prop.的方式来使用参数
console.log(prop.car)

</script>
<style scoped>
.son {
    border:1px solid #000;
    padding: 30px;
}
</style>

③.说明

在父组件中,导入子组件可以直接进行使用。

在父组件中,需要在子组件上以属性的方式进行参数传递,可以传递固定值或者动态值。

在父组件中,改变了给子组件传递的值,子组件会实时接收到最新的值,并更新视图。

在子组件中,通过defineProps来接收父组件传递的参数,参数id和父组件中子组件上的属性一致。

在子组件中,模板中可以直接使用参数,在js中要通过对象.属性的方式进行使用。

当父组件给子组件传递的参数变化时,如果传递的是个响应式对象,给响应式对象设定一个对象时,子组件没有接收到父组件最新的值,但是给对象中的属性一一赋值的,子组件是可以接收到父组件中最新的值(具体原因正在调查中)。

2.子传父(子调用父的方法)

①步骤

在父组件中给子组件标签通过@方式绑定自定义事件

在子组件通过defineEmits编译器宏生成emit方法

在子组件中触发自定义事件,并传递参数

②示例

父组件:

<script setup>
// 局部组件,导入之后就可以进行使用
import chlid from '@/components/child.vue'
import { ref } from 'vue';
const money = ref(50);
const add = () =>{
  money.value += 10;
}

const subs = (val) =>{
money.value = val;
}
</script>

<template>
  <div>
    <h3>父组件 {{ money }}
      <!-- 在父组件中改变了往子组件传递的值,子组件会接收到最新的值,并更新视图 -->
    <button @click="add"> 挣钱</button>
  </h3>
  <!-- 给子组件,以添加属性的方式进行传递,可以传递固定值或者动态值-->
    <chlid car = "BYD" :money = "money" @sub="subs"></chlid>
  </div>
</template>

子组件:

<template>
<!-- 在模板中可以直接使用参数,不需要通过prop.的方式 -->
<div class="son"> 子组件  {{ car }} - {{ money }} 
<button @click="send">花钱</button>
</div>
</template>

<script setup>
const prop = defineProps({
    money:Number,
    car:String
})
const emit = defineEmits(['sub'])
// 在js中需要prop.的方式来使用参数
console.log(prop.car)

const send = () =>{
    emit("sub",5);
}

</script>
<style scoped>
.son {
    border:1px solid #000;
    padding: 30px;
}
</style>

③说明

父组件中的自定义事件名和子组件中defineEmits数组中的时间名和emit方法中的事件名,这三个事件名必须保持一致。

3.父调用子的方法

①步骤

默认情况下载<script setup>语法糖下组件内部的属性和方法时不开放给父组件访问的,

可以通过defineExpose编译宏指定哪些属性和方法允许访问。

②示例

父组件:

<script setup>
// 局部组件,导入之后就可以进行使用
import chlid from '@/components/child.vue'
import { ref } from 'vue';
const name = ref('xiaolin');
const updateName = () => {
  name.value = 'xiaoli';
}
const money = ref(50);
const add = () =>{
  money.value += 10;
}

const subs = (val) =>{
money.value = val;
}

// 定义子组件ref对象,调用子组件的方法及属性
const childRef = ref(null);
const gerChild = () =>{
  console.log(childRef.value);
  console.log(childRef.value.info);
  childRef.value.fun1('123');
}
</script>

<template>
  <div>
    <h3>父组件 {{ money }}
      <!-- 在父组件中改变了往子组件传递的值,子组件会接收到最新的值,并更新视图 -->
    <button @click="add"> 挣钱</button>
  </h3>
  <!-- 给子组件,以添加属性的方式进行传递,可以传递固定值或者动态值-->
    <chlid ref="childRef" car = "BYD" :money = "money" @sub="subs"></chlid>
    <button @click="gerChild">获取子组件</button>
  </div>
</template>

子组件:

<template>
<!-- 在模板中可以直接使用参数,不需要通过prop.的方式 -->
<div class="son"> 子组件  {{ car }} - {{ money }} 
<button @click="send">花钱</button>
<input ref="inputRef"/>
</div>
</template>

<script setup>
import { ref,onMounted } from 'vue';
const prop = defineProps({
    money:Number,
    car:String
})
const emit = defineEmits(['sub'])
// 在js中需要prop.的方式来使用参数
console.log(prop.car)

const send = () =>{
    emit("sub",5);
}
// 模板引用
// 1.通过调用ref函数生成一个ref对象
// 2.通过ref标识进行绑定
// 通过ref对象的.value属性就能获取到绑定元素或组件的方法及属性(必须渲染完成之后才能获取)
const inputRef = ref(null);
onMounted(()=>{
    console.log(inputRef.value);
    inputRef.value.focus();
})

// 下面的属性和方法要想被父组件访问,需要defineExpose宏函数指定要访问的属性和方法
const  info = 1234556;
const fun1 = (val) =>{
    console.log("调用到了子组件的方法",val);
}
defineExpose({
    info,fun1
})
</script>
<style scoped>
.son {
    border:1px solid #000;
    padding: 30px;
}
</style>

③说明

通过defineExpose显示暴露子组件内部的属性和方法。

在父组件中通过ref函数获取到子组件的实例,然后通过.value来调用子组件的属性及方法。

4.顶层给底层传参,底层调用顶层的方法

①步骤

顶层组件通过provide函数提供数据

底层组件通过inject函数获取数据

传递参数,一般传递响应式变量

传递方法,方法中可以接收参数 

②示例

顶层组件

<script setup>
// 局部组件,导入之后就可以进行使用
import chlid from '@/components/child.vue'
import { provide, ref } from 'vue';
const name = ref('xiaolin');
const updateName = () => {
  name.value = 'xiaoli';
}
const money = ref(50);
const add = () =>{
  money.value += 10;
}

const subs = (val) =>{
money.value = val;
}

// 定义子组件ref对象,调用子组件的方法及属性
const childRef = ref(null);
const gerChild = () =>{
  console.log(childRef.value);
  console.log(childRef.value.info);
  childRef.value.fun1('123');
}
// 顶层组件给底层组件传递参数
// 在顶层组件通过provie向底层组件传递参数,数据是响应式的,在顶层组件中修改了传递给底层组件的参数,底层组件会接收到最新的值。
const title= ref("主题1");
provide("title",title);
const updateBottom = () =>{
  title.value = "主题修改了";
}
// 顶层组件给底层组件传递方法
provide('updateTitile', (newVal) =>{
  title.value = '主题修改为' + newVal;
})
</script>

<template>
  <div>
    <h1>父组件 {{ money }}
      <!-- 在父组件中改变了往子组件传递的值,子组件会接收到最新的值,并更新视图 -->
    <button @click="add"> 挣钱</button>
  </h1>
  <!-- 给子组件,以添加属性的方式进行传递,可以传递固定值或者动态值-->
    <chlid ref="childRef" car = "BYD" :money = "money" @sub="subs"></chlid>
    <button @click="gerChild">获取子组件</button>
    <!-- 修改向底层组件传递的内容 -->
    <button @click="updateBottom"> 修改向底层组件传递的内容</button>
  </div>
</template>

中间组件

<template>
<!-- 在模板中可以直接使用参数,不需要通过prop.的方式 -->
<div class="son">
     <h2>子组件  {{ car }} - {{ money }} </h2>
<button @click="send">花钱</button>
<input ref="inputRef"/>
<bottom></bottom>
</div>

</template>

<script setup>
import { ref,onMounted } from 'vue';
import bottom from './bottom.vue';
const prop = defineProps({
    money:Number,
    car:String
})
const emit = defineEmits(['sub'])
// 在js中需要prop.的方式来使用参数
console.log(prop.car)

const send = () =>{
    emit("sub",5);
}
// 模板引用
// 1.通过调用ref函数生成一个ref对象
// 2.通过ref标识进行绑定
// 通过ref对象的.value属性就能获取到绑定元素或组件的方法及属性(必须渲染完成之后才能获取)
const inputRef = ref(null);
onMounted(()=>{
    console.log(inputRef.value);
    inputRef.value.focus();
})

// 下面的属性和方法要想被父组件访问,需要defineExpose宏函数指定要访问的属性和方法
const  info = 1234556;
const fun1 = (val) =>{
    console.log("调用到了子组件的方法",val);
}
defineExpose({
    info,fun1
})
</script>
<style scoped>
.son {
    border:1px solid #000;
    padding: 30px;
}
</style>

底层组件

<template>
<div> 
    <h3>我是底层组件 - {{ title }}</h3>
    <button @click="update">调用顶层组件的方法</button>
</div>
</template>

<script setup>
import { inject } from 'vue';

// 底层组件通过inject接收顶层组件的参数
const title = inject('title');

// 底层组件通过inject接收顶层组件的方法
const updateTitile = inject('updateTitile');

const update = () =>{
    updateTitile('底层调用顶层');
}

</script>

③说明

通过provide及inject实现顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信。如果不使用这种方式,只能一级级组件进行通信,或者使用全局状态管理(如pinia)。

在顶层组件中通过provide提供响应式变量及方法,在底层组件中铜鼓inject可以进行调用。

5.模板引用

①步骤

调用ref函数生成一个ref对象。

通过ref标识绑定ref对象到标签中。

②示例

<template>
<!-- 在模板中可以直接使用参数,不需要通过prop.的方式 -->
<div class="son"> 子组件  {{ car }} - {{ money }} 
<button @click="send">花钱</button>
<input ref="inputRef"/>
</div>
</template>

<script setup>
import { ref,onMounted } from 'vue';
const prop = defineProps({
    money:Number,
    car:String
})
const emit = defineEmits(['sub'])
// 在js中需要prop.的方式来使用参数
console.log(prop.car)

const send = () =>{
    emit("sub",5);
}
// 模板引用
// 1.通过调用ref函数生成一个ref对象
// 2.通过ref标识进行绑定
// 通过ref对象的.value属性就能获取到绑定元素或组件的方法及属性(必须渲染完成之后才能获取)
const inputRef = ref(null);
onMounted(()=>{
    console.log(inputRef.value);
    inputRef.value.focus();
})

const  info = 1234556;
const fun1 = () =>{
    console.log("调用到了子组件的方法");
}
</script>
<style scoped>
.son {
    border:1px solid #000;
    padding: 30px;
}
</style>

上面示例实现了画面加载后焦点放在输入框上。 

③说明

通过ref标识获取真实的dom对象或者组件对象实例,这就就通过dom对象或者组件实例来调用方法和属性。常见的示例如下:

获取form表单的dom对象,调用validate()进行校验处理。

获取imput输入框的dom对象,调用focus(),将焦点放在输入框上。

获取子组件的对象实例,调用子组件的方法或者获取子组件的属性。

注意:通过ref方式获取dom对象有一个前提,必须是页面渲染完成之后才能获取到,最早在onmounted中可以获取到。

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值