组件通信
如果父节点和子节点通信,可以使用props
子节点跟父节点通信,可以使用this.$emit()
但是如果节点关系复杂,使用上面两种方法会很代码变得十分复杂,难以维护
可以使用 provide(提供) 和 inject(注入) 实现组件通信(冒泡机制)
index.vue
<template>
<div>
<!-- <ChildrenA /> -->
<ChildrenA1 />
</div>
</template>
<script>
import ChildrenA from "./ChildrenA";
import ChildrenA1 from "./ChildrenA_a";
export default {
components: {
ChildrenA
// ChildrenA1
}
};
</script>
<style>
.border,
.border1,
.border2 {
border: 1px solid #000;
padding: 10px 0;
margin: 10px 10px 0;
}
.border1 {
border-color: #ccc;
}
.border2 {
border-color: #eee;
}
</style>
ChildrenA.vue
把 provide 处的注释调整下,才会有反应,因为color并不是响应式的数据
<template>
<div class="border">
<h1>A 结点</h1>
<button @click="() => changeColor()">改变color</button>
<ChildrenB />
<ChildrenC />
<ChildrenD />
</div>
</template>
<script>
import ChildrenB from "./ChildrenB";
import ChildrenC from "./ChildrenC";
import ChildrenD from "./ChildrenD";
export default {
components: {
ChildrenB,
ChildrenC,
ChildrenD
},
provide() {
return {
theme: {
color: this.color
}
};
},
// provide() {
// return {
// theme: this
// };
// },
data() {
return {
color: "blue"
};
},
methods: {
changeColor(color) {
if (color) {
this.color = color;
} else {
this.color = this.color === "blue" ? "red" : "blue";
}
}
}
};
</script>
ChildrenA_a.vue
<template>
<div class="border">
<h1>A 结点</h1>
<button @click="() => changeColor()">改变color</button>
<ChildrenB />
<ChildrenC />
<ChildrenD />
</div>
</template>
<script>
import Vue from "vue";
import ChildrenB from "./ChildrenB";
import ChildrenC from "./ChildrenC";
import ChildrenD from "./ChildrenD";
export default {
components: {
ChildrenB,
ChildrenC,
ChildrenD
},
provide() {
this.theme = Vue.observable({
color: "blue"
});
return {
theme: this.theme
};
},
methods: {
changeColor(color) {
if (color) {
this.theme.color = color;
} else {
this.theme.color = this.theme.color === "blue" ? "red" : "blue";
}
}
}
};
</script>
ChildrenB.vue
<template functional>
<div class="border1">
<h2>B 结点</h2>
</div>
</template>
ChildrenC.vue
如果C节点的provide注释打开,就会阻止冒泡,因为color并不是一个响应式的数据
<template>
<div class="border1">
<h2>C 结点</h2>
<ChildrenE />
<ChildrenF />
</div>
</template>
<script>
import ChildrenE from "./ChildrenE";
import ChildrenF from "./ChildrenF";
export default {
components: {
ChildrenE,
ChildrenF
}
// provide() {
// return {
// theme: {
// color: "green"
// }
// };
// }
};
</script>
ChildrenD.vue
<template>
<div class="border1">
<h2>D 结点</h2>
<ChildrenG />
<ChildrenH />
<ChildrenI />
</div>
</template>
<script>
import ChildrenG from "./ChildrenG";
import ChildrenH from "./ChildrenH";
import ChildrenI from "./ChildrenI";
export default {
components: {
ChildrenG,
ChildrenH,
ChildrenI
}
};
</script>
ChildrenE.vue
<template>
<div class="border2">
<h3 :style="{ color: theme.color }">E 结点</h3>
<button @click="handleClick">改变color为green</button>
</div>
</template>
<script>
export default {
components: {},
inject: {
theme: {
default: () => ({})
}
},
methods: {
handleClick() {
if (this.theme.changeColor) {
this.theme.changeColor("green");
}
}
}
};
</script>
ChildrenF.vue
通过 from 的特性,取别名<template>
<div class="border2">
<h3 :style="{ color: theme1.color }">F 结点</h3>
</div>
</template>
<script>
export default {
components: {},
inject: {
theme1: {
from: "theme",
default: () => ({})
}
}
};
</script>
ChildrenG.vue
<template>
<div class="border2">
<h3>G 结点</h3>
</div>
</template>
<script>
export default {};
</script>
ChildrenH.vue
<template>
<div class="border2">
<h3>H 结点</h3>
</div>
</template>
<script>
export default {};
</script>
ChildrenI.vue
函数式组件
<template functional>
<div class="border2">
<h3 :style="{ color: injections.theme.color }">I 结点</h3>
</div>
</template>
<script>
export default {
inject: {
theme: {
default: () => ({})
}
}
};
</script>