vue组件间通信方式(父子通信、兄弟通信、跨级通信)

  1. props/$emit
  2. v-slot
  3. r e f s / refs/refs/parent/c h i l d r e n / children/children/root
  4. a t t r s / attrs/attrs/listeners
  5. provide/inject
  6. eventBus
  7. vuex
    父子通信:1,2,3,4,5,6,7
    兄弟通信:6,7
    跨级通信:4,5,6,7

1. props/$emit

父组件通过props向子组件传递数据,子组件通过$emit向父组件传递数据。

父组件:

<son :msg="msgData" :fn="myFunc" @closeDialog="closeDialog"></child>

子组件:

<div>{{msg}}</div>
<button @click="fn">

<a @click="close"></a>

props: ['msg', 'fn'],

method: {
	close() {
		this.$emit('closeDialog');
	}
}

2. v-slot

适用于父组件向子组件传值。
《vue—插槽》:https://blog.csdn.net/bidepanm/article/details/124462309?spm=1001.2014.3001.5501

3. $refs/$parent/$children/$root

通过$parent访问到的是上一级父组件的实例,可以使用 $root来访问根组件的实例。
在组件中使用$children拿到的是所有的子组件的实例,它是一个数组,并且是无序的。

4. $attrs/$listeners

实现祖与后代组件通信,一般用于实现祖孙组件通信。

$attrs的用法(祖传孙):

正常情况下:父组件通过v-bind绑定一个数据传递给子组件,子组件通过props接收到就可以在子组件的html中使用了。但是,如果父组件v-bind传递给子组件,子组件没有用props接收呢?
注意:这个时候,父组件传递过来的数据就会被挂载(赋值)到这个子组件自带的对象$attrs上面,所以:

$attrs就是一个容器对象,这个容器对象会存放:父组件传过来的且子组件未使用props声明接收的数据

爷组件:

<template>
  <div id="app">
    我是爷组件
    <fu
      :msg1="msg1"
      :msg2="msg2"
      :msg3="msg3"
      :msg4="msg4"
    ></fu>
  </div>
</template>

<script>
export default {
  components: {
    father
  },
  data() {
    return {
      msg1: "aaa",
      msg2: "bbb",
      msg3: ["a", "b", "c"],
      msg4: {
        name: "haha",
        age: 22,
      },
    };
  },
};
</script>

父组件:
在父组件中我们只在props中接收msg1,另外三个我们不在props中接收。于是另外三个未在props中接收的,会自动被存放在 $attrs 这个容器对象中去。

<template>
  <div>
    <h2>{{ msg1 }}</h2>
    <h2>{{ $attrs.msg2}}</h2>
    <h2>{{ $attrs.msg3}}</h2>
    <h2>{{ $attrs.msg4}}</h2>
  </div>
</template>

<script>
export default {
  name: 'Father',
  props: {
    msg1: {
      type: String,
      default: '',
    },
  }
};
</script>

孙组件:
爷组件传递给孙组件的逻辑流程就是,通过爷组件首先传递给父组件,当然父组件不在props中接收,那么爷组件传递给父组件的数据就会存放到父组件的 $ attrs对象中里面了,然后,再通过v-bind="$attrs",把这个$ attr传递给孙组件,在孙组件中使用props就能接收到$attrs中的数据了,这样就实现了,祖孙之间的数据传递。

<template>
  <div class="sunClass">
    我是孙子组件
    <h2>接收爷组件数据:-->{{ msg2 }}</h2>
    <h2>接收爷组件数据:-->{{ msg3 }}</h2>
    <h2>接收爷组件数据:-->{{ msg4 }}</h2>
  </div>
</template>

<script>
export default {
  name: 'Sun',
  // $attrs一般搭配interitAttrs 一块使用
  inheritAttrs: false, // 默认会继承在html标签上传递过来的数据,类似href属性的继承
  /*
    孙子组件通过props,就能接收到父组件传递过来的$attrs了,就能拿到里面的数据了,也就是:
    爷传父、父传子。即:祖孙之间的数据传递。
  */ 
  props: {
    msg2: {
      type: String,
      default: '',
    },
    msg3: {
      type: Array,
      default: () => {
        return [];
      },
    },
    msg4: {
      type: Object,
      default: () => {
        return {};
      },
    },
  }
};

$listeners的用法:

使用$listeners可以实现孙组件的数据传递到爷组件中去,$listeners可以将子组件emit的方法通知到爷组件。

  1. 在中间的父组件中加上$listenners
<sun v-bind="$attrs" v-on="$listeners"></sun>
  1. 爷组件中定义事件方法
<template>
  <div id="app">
    我是爷组件
    <h3>{{ fromSunData }}</h3>
    <fu :msg1="msg1" :msg2="msg2" :msg3="msg3" :msg4="msg4" 
        @fromSun="fromSun">
    </fu>
  </div>
</template>

<script>
export default {
  components: {
    father,
  },
  data() {
    return {
      msg1: "aaa",
      msg2: "bbb",
      msg3: ["a", "b", "c"],
      msg4: {
        name: "haha",
        age: 22,
      },
      fromSunData: "",
    };
  },
  methods: {
    fromSun(payload) {
      this.fromSunData = payload;
    },
  },
};
</script>
  1. 孙组件去触发爷组件的事件方法
<template>
  <div>
    我是孙子组件
    <h2>接收爷组件:-->{{ msg2 }}</h2>
    <h2>接收爷组件:-->{{ msg3 }}</h2>
    <h2>接收爷组件:-->{{ msg4 }}</h2>
    <el-button size="small" type="primary" plain @click="sendToZu">孙传祖</el-button>
  </div>
</template>

<script>
export default {
  // $attrs一般搭配interitAttrs 一块使用
  inheritAttrs: false, // 默认会继承在html标签上传递过来的数据,类似href属性的继承
  props: {
    msg2: {
      type: String,
      default: '',
    },
    msg3: {
      type: Array,
      default: () => {
        return [];
      },
    },
    msg4: {
      type: Object,
      default: () => {
        return {};
      },
    },
  },
  data() {
    return {
      data: "来自孙组件的数据",
    };
  },
  methods: {
    sendToZu() {
      // 孙组件能够触发爷组件的fromSun方法的原因还是因为父组件中有一个$listeners作为中间人,去转发这个事件的触发
      this.$emit("fromSun", this.data);
    },
  },
};
</script>

5. provide/inject

实现祖与后代组件通信,一般用于实现祖孙组件通信。

父组件有一个provide选项来提供数据,后代组件有一个inject选项来开始使用这些数据。

祖组件中:

setup() {
	....
	let car = reactive({
		name: 'xxx',
		price: '10w'
	})
	provide('car', car)
}

后代组件中:

setup() {
	....
	const car = inject('car')
	return {car}
}

下面写法可以访问到祖组件中所有的属性和方法:

祖组件:

provide() {
 return {
    app: this
  };
}
data() {
 return {
    num: 1
  };
}

后代组件:

inject: ['app']
console.log(this.app.num)

6. eventBus

《vue--------eventBus使用》:https://blog.csdn.net/bidepanm/article/details/118617845?spm=1001.2014.3001.5501

7. vuex

《vuex的基本使用》:https://blog.csdn.net/bidepanm/article/details/124463616?spm=1001.2014.3001.5501


版权声明:本文为bidepanm原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。