有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问根组件。
方法汇总:
- 父组件访问子组件:
$children
或者$refs
- 子组件访问父组件:
$parent
- 子组件访问根组件(通过 new Vue 创建的根 Vue 实例):
$root
下面是详细演示:
1. 父组件访问子组件
1.1 使用 $children
在父组件中使用 this.$children
拿到的是一个数组类型,它包含所有子组件实例。
<div id="app">
<cpn></cpn>
<cpn></cpn>
<button @click="btnClick">按钮</button>
</div>
<template id="cpn">
<div>
<h1>我是子组件</h1>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
},
methods: {
btnClick() {
//1.拿到所有子组件,是一个数组
console.log(this.$children);
//2.拿到一个组件实例,可以直接访问子组件中的方法和 data 中的数据
this.$children[0].showMessage();
console.log(this.$children[0].name);
}
},
components: {
cpn: {
template: '#cpn',
data() {
return {
name: 'webchang'
}
},
methods: {
showMessage() {
console.log('我是子组件');
}
}
}
}
});
</script>
1.2 使用 $refs
$children
的缺陷:
- 通过
$children
访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。 - 但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化。
- 有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用
$refs
$refs
的使用:
$refs
和ref
指令通常是一起使用的。- 首先,我们在子组件上添加一个
ref
属性,相当于给某一个子组件绑定一个特定的ID。 - 其次,
this.$refs
拿到的是所有标有 ref 属性的子组件(如果一个子组件实例没有 ref 属性,通过这种方式是拿不到的),最后拿到的是一个 对象,属性名是子组件实例的 ref 属性,属性值是该组件实例。 - 通过
this.$refs.ID
就可以访问到该组件。
<div id="app">
<cpn ref="child1"></cpn>
<cpn ref="child2"></cpn>
<!-- 这个子组件实例没有 ref 属性,通过 this.$refs 方式拿不到这个组件实例 -->
<cpn></cpn>
<button @click="btnClick">按钮</button>
</div>
<template id="cpn">
<div>
<h1>我是子组件</h1>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello"
},
methods: {
btnClick() {
console.log(this.$refs);
console.log(this.$refs.child1);
console.log(this.$refs.child1.name);
this.$refs.child1.showMessage();
}
},
components: {
cpn: {
template: '#cpn',
data() {
return {
name: 'webchang'
}
},
methods: {
showMessage() {
console.log('我是子组件');
}
}
}
}
});
</script>
结果如图所示:
2. 子访问父
2.1 使用 $parent
如果我们想在子组件中直接访问父组件,可以通过 $parent
注意事项:
- 尽管在Vue开发中,我们允许通过
$parent
来访问父组件,但是在真实开发中尽量不要这样做。 - 子组件应该尽量避免直接访问父组件的数据,因为这样耦合度太高了。
- 如果我们将子组件放在另外一个组件之内,很可能该父组件没有对应的属性,往往会引起问题。
- 另外,更不好的是通过
$parent
直接修改父组件的状态,那么父组件中的状态将变得飘忽不定,很不利于我的调试和维护。
2.2 使用 $root
使用 $root
可以直接访问 Vue 根实例
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h1>我是子组件的标题</h1>
<button @click="btnClick">我是子组件的按钮</button>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
},
components: {
cpn: {
template: '#cpn',
methods: {
btnClick() {
console.log(this.$parent);
console.log(this.$root);
}
}
}
}
});
</script>
在这个代码中,子组件的父组件正好是 Vue根实例