20
2021
01

为什么不使用provide与inject?

因为它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。

然后有两种场景它不能很好的解决:

父组件向子组件(支持跨级)传递数据;

子组件向父组件(支持跨级)传递数据。

代码如下:


  • emitter.js



function broadcast(componentName, eventName, params) {

 this.$children.forEach(child => {

  const name = child.$options.name;

 

  if (name === componentName) {

   child.$emit.apply(child, [eventName].concat(params));

  } else {

   // todo 如果 params 是空数组,接收到的会是 undefined

   broadcast.apply(child, [componentName, eventName].concat([params]));

  }

 });

}

export default {

 methods: {

  dispatch(componentName, eventName, params) {

   let parent = this.$parent || this.$root;

   let name = parent.$options.name;

 

   while (parent && (!name || name !== componentName)) {

    parent = parent.$parent;

 

    if (parent) {

     name = parent.$options.name;

    }

   }

   if (parent) {

    parent.$emit.apply(parent, [eventName].concat(params));

   }

  },

  broadcast(componentName, eventName, params) {

   broadcast.call(this, componentName, eventName, params);

  }

 }

};


  • parent.vue


<template>

 <div>

  <h1>我是父组件</h1>

  <button @click="handleClick">触发事件</button> <child />

 </div>

</template>

<script>

import Emitter from "@/mixins/emitter.js";

import Child from "./child";

export default {

 name: "componentA",

 mixins: [Emitter],

 created() {

  this.$on("child-to-p", this.handleChild);

 },

 methods: {

  handleClick() {

   this.broadcast("componentB", "on-message", "Hello Vue.js");

  },

  handleChild(val) {

   alert(val);

  }

 },

 components: {

  Child

 }

};

</script>



  • child.vue


<template>

 <div>我是子组件</div>

</template>

<script>

import Emitter from "@/mixins/emitter.js";

export default {

 name: "componentB",

 mixins: [Emitter],

 created() {

  this.$on("on-message", this.showMessage);

  this.dispatch("componentA", "child-to-p", "hello parent");

 },

 methods: {

  showMessage(text) {

   window.alert(text);

  }

 }

};

</script>

这样就能实现跨级组件自定义通信了,但是,要注意其中一个问题:订阅必须先于发布,也就是说先有on再有emit



« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。