5.组件通信方式5-$attrs
$attrs的概念:
在Vue中,$attrs
是一个特殊的属性,用于访问父组件向子组件传递的非特定属性。它可以让子组件轻松地获取父组件传递的属性,而无需在子组件中显式声明这些属性。
想象一下你有一个父组件和一个子组件,你希望通过属性将一些数据从父组件传递到子组件。通常情况下,你需要在子组件中定义这些属性,然后通过父组件将数据传递给子组件。
但是,有时候你可能希望传递一些额外的属性,这些属性在子组件中并没有声明。这时候,$attrs
就派上用场了。
当你在父组件中将属性传递给子组件时,如果子组件没有显式声明这些属性,那么这些属性会被收集到 $attrs
对象中。子组件可以通过访问 $attrs
来获取这些传递的额外属性。
这就好像是你在给子组件写一封信时,除了信中明确提到的事项外,你还可以附带一些额外的内容。而子组件可以通过查看信的附件来获取这些额外的内容。
通过使用 $attrs
,子组件可以轻松地访问父组件传递的这些额外属性,而无需在子组件中显式声明它们。这样可以使得组件之间的通信更加灵活和方便。
5.1父组件传孙组件
概述:$attrs
用于实现当前组件的父组件,向当前组件的子组件通信(祖→孙)。
此时需要建立这三个组件
1.父组件(Father.vue)
2.子组件(Child.vue)
3.孙组件(GrandChild.vue)
1. 在Father.vue文件里面增添一些响应式数据
2.先从父组件传来给子组件
3.实现组件再传给孙组件,孙组件在接收即可
实现效果:
5.2孙组件传给父组件
现在我们让孙组件可以传递一个参数,让父组件的响应式a接收这个参数
1.定义一个updataA方法
2.放在子组件进行接收
3.子组件内容不用变
4.孙组件内容增添
6.组件通信方式6-$refs、$parent
$refs、$parent的概念:
在Vue中,$refs
和 $parent
是用于在组件之间进行通信的特殊属性。
首先,让我们来了解 $refs
。当你在Vue模板中给一个元素或组件添加 ref
属性时,你就可以通过 $refs
来访问该元素或组件的引用。简单来说,$refs
就像是给元素或组件起了一个名字标签,让你可以在Vue实例中轻松地引用它们。
想象一下你有一个组件,里面有一个按钮元素,你希望在Vue实例中能够获取到这个按钮并进行一些操作。你可以在按钮上添加一个 ref
属性,比如 ref="myButton"
。然后,你就可以通过 $refs.myButton
来访问这个按钮了。
$refs
是一个对象,它的属性名就是你在 ref
属性中指定的名字,而对应的属性值就是对应的元素或组件的引用。通过访问 $refs
属性,你就可以像操作普通的DOM元素一样操作引用的元素或组件。
接下来,我们来看看 $parent
。在Vue组件的层级结构中,每个组件都可以有一个父组件。当你需要在子组件中访问父组件的数据或方法时,可以使用 $parent
。
想象一下你有一个父组件和一个子组件,你希望在子组件中获取父组件的某个属性或调用父组件的方法。你可以通过 $parent
来实现这个目标。
$parent
是一个特殊属性,它可以让你在子组件中访问父组件实例。通过 $parent
,你可以直接访问父组件的数据属性或方法,就好像你是在父组件内部一样。
-
概述:
-
$refs
用于 :父→子。 -
$parent
用于:子→父。
-
-
原理如下:
此时需要建立这三个组件
1.父组件(Father.vue)
2.子组件1(Child1)
3.子组件2(Child2)
分别给这三个组件增添点响应式数据
6.1在父组件修改子组件的内容
现在要在父组件设置一个按钮,点击按钮可以将Child的"奥特曼"修改成"小猪佩奇"
1.在子组件(Chiled1)中用defineExpose()将要给的数据暴露出去。
2.父组件用ref接收并修改
同理
父亲组件通过按钮将Child2组件的电脑"联想"修改成”华为“
跟上面步骤一样,就不赘述了
6.2在父组件用$ref修改所有子组件
1.在父组件通过点击事件的$refs将所有的孩子组件的书都增添三本
2.所有孩子组件都要将书这个数据暴露出去
6.3在子组件用$parent修改父组件
现在在Child1上通过一个按钮,将父亲的房产减一。
1.在点击事件上用$parent接收父组件实例
2.在父组件同样要暴露出来
Father.vue代码:
<template>
<div class="father">
<h3>父组件</h3>
<h4>房产:{{ house }}</h4>
<button @click="changeToy">修改Child1的玩具</button>
<button @click="changeComputer">修改Child2的电脑</button>
<button @click="getAllChild($refs)">让所有孩子的书变多</button>
<Child1 ref="c1"/>
<Child2 ref="c2"/>
</div>
</template>
<script setup lang="ts" name="Father">
import Child1 from './Child1.vue'
import Child2 from './Child2.vue'
import { ref,reactive } from "vue";
let c1 = ref()
let c2 = ref()
// 数据
let house = ref(4)
// 方法
function changeToy(){
c1.value.toy = '小猪佩奇'
}
function changeComputer(){
c2.value.computer = '华为'
}
function getAllChild(refs:{[key:string]:any}){
console.log(refs)
for (let key in refs){
refs[key].book += 3
}
}
// 向外部提供数据
defineExpose({house})
</script>
<style scoped>
.father {
background-color: rgb(165, 164, 164);
padding: 20px;
border-radius: 10px;
}
.father button {
margin-bottom: 10px;
margin-left: 10px;
}
</style>
Child1.vue代码:
<template>
<div class="child1">
<h3>子组件1</h3>
<h4>玩具:{{ toy }}</h4>
<h4>书籍:{{ book }} 本</h4>
<button @click="minusHouse($parent)">干掉父亲的一套房产</button>
</div>
</template>
<script setup lang="ts" name="Child1">
import { ref } from "vue";
// 数据
let toy = ref('奥特曼')
let book = ref(3)
// 方法
function minusHouse(parent:any){
parent.house -= 1
}
// 把数据交给外部
defineExpose({toy,book})
</script>
<style scoped>
.child1{
margin-top: 20px;
background-color: skyblue;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px black;
}
</style>
Child2.vue代码:
<template>
<div class="child2">
<h3>子组件2</h3>
<h4>电脑:{{ computer }}</h4>
<h4>书籍:{{ book }} 本</h4>
</div>
</template>
<script setup lang="ts" name="Child2">
import { ref } from "vue";
// 数据
let computer = ref('联想')
let book = ref(6)
// 把数据交给外部
defineExpose({computer,book})
</script>
<style scoped>
.child2{
margin-top: 20px;
background-color: orange;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px black;
}
</style>
7.组件通信方式7-provide、inject
provide、inject的概念:
在Vue中,provide
和 inject
是一对用于实现祖先组件向后代组件传递数据的特殊选项。
首先,让我们来了解 provide
。当你在祖先组件中使用 provide
选项时,你可以定义一些数据或方法,并将它们提供给后代组件。简单来说,provide
就像是祖先组件向后代组件提供了一些东西,就像你给孩子准备了一些礼物。
想象一下你有一个祖先组件,里面有一些数据或方法,你希望能够将它们传递给后代组件使用。你可以在祖先组件中使用 provide
选项来定义这些数据或方法,然后在后代组件中使用 inject
来接收它们。
接下来,我们来看看 inject
。当你在后代组件中使用 inject
选项时,你可以接收祖先组件通过 provide
提供的数据或方法。简单来说,inject
就像是后代组件从祖先组件那里接收了一些礼物。
inject
是一个特殊选项,它允许你在后代组件中接收祖先组件提供的数据或方法。通过使用 inject
,你可以像在后代组件中普通的数据属性一样使用这些从祖先组件传递过来的数据或方法。
使用 provide
和 inject
可以让你在组件层级结构中方便地共享数据或方法,而无需通过逐层传递 props 或事件来实现。这对于跨多个层级的组件之间的通信非常有用。
-
概述:实现祖孙组件直接通信
-
具体使用:
-
在祖先组件中通过
provide
配置向后代组件提供数据 -
在后代组件中通过
inject
配置来声明接收数据
-
这里创建三个组件
此时需要建立这三个组件
1.父组件(Father.vue)
2.子组件(Child)
3.孙组件(GrandChild)
展现:
在这里的子组件没什么作用,只是为了突出父组件可以直接传数据给孙组件时,可以不像$attrs一样要打扰到子组件。
7.1父组件给孙组件传数据
现在开始传数据啦
1.在父组件用provide提供数据给子组件
2.在子组件用inject接收数据
注意:先把上面父组件的‘qian’ 换成‘money’,‘che’换成‘car’
前期是为了区分,现在不用了
7.2孙组件给父组件传数据
现在在孙组件通过一个按钮可以修改父组件的money
1.在父组件修改内容
补充:
在上面图的第二步,provide中,money不要加上.value,不然,就不会是响应式了
比如:
2.在子组件中修改内容
显示:
最后,子组件都没有用上,所以只是想告诉你,父组件给孙组件传递数据可以不影响子组件
父组件(Father.vue)代码:
<template>
<div class="father">
<h3>父组件</h3>
<h4>银子:{{ money }}万元</h4>
<h4>车子:一辆{{car.brand}}车,价值{{car.price}}万元</h4>
<Child/>
</div>
</template>
<script setup lang="ts" name="Father">
import Child from './Child.vue'
import {ref,reactive,provide} from 'vue'
let money = ref(100)
let car = reactive({
brand:'奔驰',
price:100
})
function updateMoney(value:number){
money.value -= value
}
// 向后代提供数据
provide('moneyContext',{money,updateMoney})
provide('car',car)
</script>
<style scoped>
.father {
background-color: rgb(165, 164, 164);
padding: 20px;
border-radius: 10px;
}
</style>
孙组件(GrandChild.vue)代码:
<template>
<div class="grand-child">
<h3>我是孙组件</h3>
<h4>银子:{{ money }}</h4>
<h4>车子:一辆{{car.brand}}车,价值{{car.price}}万元</h4>
<button @click="updateMoney(6)">花爷爷的钱</button>
</div>
</template>
<script setup lang="ts" name="GrandChild">
import { inject } from "vue";
let {money,updateMoney} = inject('moneyContext',{money:0,updateMoney:(param:number)=>{}})
let car = inject('car',{brand:'未知',price:0})
</script>
<style scoped>
.grand-child{
background-color: orange;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px black;
}
</style>
8.pinia
Vue3从入门到实战:掌握状态管理库pinia(上部分)-CSDN博客
Vue3从入门到实战:掌握状态管理库pinia(下部分)-CSDN博客