目录
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中可以获取到。