组件通信

如果父节点和子节点通信,可以使用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>

results matching ""

    No results matching ""