多层组件传值
在组件中传值,在父子级组件很好就实现了,但是如果第一层的组件向第六层或者更高的层次传值时,我们就非常难办了,在我们以前学习的知识来实现。我们只有将通过给每个组件中设置属性,来依次接收它的父组件传给它的值;当我们需要向第一层传回数据时,我们又要给每个组件设置自定义事件,依次传递。可见非常的麻烦,所以提供了多层传值的方法。
$listeners和$attrs
使用方法非常简单只需要在路过的组件上v-bind="$attrs" v-on="$listeners"
我们来三个组件来演示父组件向孙组件传数据,孙数据向父组件传数据。
box2孙组件代码:创建属性来接收爷爷组件传来的数据,创建自定义事件向爷爷组件传值
<template>
<div class="box2">
<h3>box3组件</h3>
<p>{{title}}</p>
<button @click="fn">点击修改爷爷组件数据</button>
</div>
</template>
<script>
export default{
props:["title"],
methods: {
fn(){
this.$emit("updategrand",this.msg)
}
},
data() {
return {
msg:"我是孙组件的数据"
}
},
}
</script>
<style>
.box2{
width: 100px;
height:150px;
background-color: yellow;
}
</style>
box1父组件:就是起着一个桥梁的作用。
<template>
<div class="box1">
<h2>box1组件</h2>
<!-- box1也可以获取传递的数据使用 -->
<div>{{$attrs.title}}</div>
<Box2 v-bind="$attrs" v-on="$listeners"></Box2>
</div>
</template>
<script>
import Box2 from "./box2.vue"
export default{
components:{
Box2
},
}
</script>
<style>
.box1{
width: 200px;
height:200px;
background-color: aqua;
}
</style>
App爷爷组件,接收自定义事件传来的值,并向孙子组件传值
<template>
<div class="app">
<h1>app父组件</h1>
<div>{{this.msg}}</div>
<Box1 :title="msg" @updategrand="fm"></Box1>
</div>
</template>
<script>
import Box1 from "@/components/box1.vue"
export default {
data() {
return {
msg:"爷爷组件的数据"
}
},
components:{
Box1
},
methods: {
fm(arg){
this.msg=arg
}
},
}
</script>
<style>
.app{
width: 300px;
height: 400px;
background-color: aquamarine;
}
</style>
页面效果:
点击按钮后:
获取组件
尽管框架为我们提供了多层组件传值的方法,但是我们还是要一层一层的去配置v-bind="$attrs"和v-on="$listeners"。
这里讲解一种更加方便的方式,就像以前学习JS的DOM时获取父节点、子节点们。
我们组件也可以获取,Vue为我们提供了四个获取组件的方法:
$parent:获取父组件对象,可直接操作父组件的data数据,不需要再使用属性传值,但是容易出现渲染混乱之后只渲染一个的情况;
$children:获取子组件们,返回的是一个数组,不能保证顺序,也不是响应式的;
$root:获取根组件;
$refs:可以在组件或者原生元素绑定ref属性(类似于id),在通过$refs来获取对应的组件或元素节点,只会在组件渲染完成之后生效,并且它们不是响应式的。你应该避免在模板或计算属性中访问 $refs。
我们来用一用,我们在上面box1组件中来依次在控制台都打印一下:
代码:
<template>
<div class="box1">
<h2>box1组件</h2>
<!-- box1也可以获取传递的数据使用 -->
<div>{{$attrs.title}}</div>
<Box2 v-bind="$attrs" v-on="$listeners" ref="tt1"></Box2>
</div>
</template>
<script>
import Box2 from "./box2.vue"
export default{
components:{
Box2
},
mounted() {
console.log(this.$parent);
console.log(this.$root);
console.log(this.$children);
console.log(this.$refs.tt1);
},
}
</script>
<style>
.box1{
width: 200px;
height:200px;
background-color: aqua;
}
</style>
当页面渲染完成时控制台的打印情况:
可见都成功获取了,而且它们就是DOM操作时一样可以连调,如box1组件对象.$parent.$parent就可以得到其的爷爷组件对象。
当我们获取到了对应的组件对象就可以操作组件内的数据。