总结一下 vue2 组件之间的通信

649 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 5 天,点击查看活动详情

start

  • 最近在学习 vue3,在学习 vue3 的 之前。先总结一下,vue2 中的组件之间的通信;

以下示例皆为 vue2

1.父组件传值给子组件,利用 props

父组件 app.vue

<template>
  <div id="app">
    <boxA :name="appName" :age="appAge" />
  </div>
</template><script>
import boxA from './boxA.vue'export default {
  name: 'App',
  data() {
    return {
      appName: '我是app页面的name',
      appAge: '我是app页面的age 123',
    }
  },
  components: {
    boxA,
  },
}
</script>

子组件 boxA.vue

<template>
  <div class="box">
    我是 A盒子
    <pre>
     我有这些属性:
​
      {{ name }}
    </pre>
  </div>
</template><script>
export default {
  name: 'boxA',
  props: {
    name: {
      type: String, // 限制类型
      default: '', // 设置默认值
      require: true, // 是否必传
    },
  },
}
</script>

2.子组件和父组件通信 $emit

父组件 app.vue

<template>
  <div id="app">
    主应用
​
    <boxA @say="sayApp" />
  </div>
</template><script>
import boxA from './boxA.vue'export default {
  name: 'App',
  components: {
    boxA,
  },
  methods: {
    sayApp(value) {
      console.log('hello', value)
    },
  },
}
</script>

子组件 boxA.vue

<template>
  <div class="box">
    <span @click="handleClick">你好</span>
  </div>
</template><script>
export default {
  name: 'boxA',
  methods: {
    handleClick() {
      this.$emit('say', '输出的参数')
    },
  },
}
</script>

3. 跨多级组件通信

/*新建一个Vue实例作为中央事件总线*/
let event = new Vue()
​
/*监听事件*/
event.$on('eventName', (val) => {
  //......do something
})
​
/*触发事件*/
event.$emit('eventName', 'this is a message.')

4.跨多级组件数据通信

vuex4.

5. 父-》子-》孙 三个层级之间的组件通信 $attrs $listeners

有这么一个场景,组件 A 中有组件 B,组件 B 中有 C。AC 之间通信怎么办?

  • 使用父子通信,B 组件中会有很多冗余代码。
  • 使用事件总线,不太利于管理;
  • 使用 vuex,有点大材小用;

在 vue2.4 版本之后,添加了这么几个属性:

  • $attrs
  • $listeners

$attrs

image-20220804115609200.png

  • vm 上的属性。所以我们可以直接在组件中,this.$attrs打印出来;
  • 2.4.0 新增的属性;
  • 简单理解就是一个对象。所有父组件传递给子组件的值,当子组件没有用 prop 属性接收,就会存储在this.$attrs中。(class 和 style 除外)

image-20220804134736441.png

$listeners

  • vm 上的属性。所以我们可以直接在组件中,this.$listeners打印出来;
  • 2.4.0 新增的属性;
  • 简单理解就是一个对象。所有父组件给子组件绑定到事件会存储在this.$listeners中,(不含 .native 修饰器的)

有什么用?

想象我们的场景:

  1. A 组件和 C 组件通信;
  2. A 传递数据给 B,绑定事件到 B 上。
  3. 可以在 B 中通过 this.$attrsthis.$listeners 拿到数据和事件
  4. 一起传递给 C 组件。

例如:

父组件 app.vue

<template>
  <div id="app">
    <boxA :name="appName" :age="appAge" @fn1="appFn1" @fn2="appFn2" />
  </div>
</template><script>
import boxA from './boxA.vue'export default {
  name: 'App',
  data() {
    return {
      appName: '我是app页面的name',
      appAge: '我是app页面的age 123',
    }
  },
  components: {
    boxA,
  },
  methods: {
    appFn1(value) {
      console.log('appFn1', value)
    },
    appFn2(value) {
      console.log('appFn2', value)
    },
  },
}
</script>

子组件 boxA.vue

<template>
  <div class="box">
    我是 A盒子
    <pre>
     我有这些属性:
​
      {{ name }}
    </pre>
​
    <!-- !!!这里可以再来一个组件  boxB; 通过 v-bind="$attrs" v-on="$listeners" 就能在boxB中收到数据了-->
    <!-- <boxB v-bind="$attrs" v-on="$listeners"> -->
  </div>
</template><script>
export default {
  name: 'boxA',
  inheritAttrs: false,
  props: {
    name: {
      type: String, // 限制类型
      default: '', // 设置默认值
      require: true, // 是否必传
    },
  },
  created() {
    console.log(this)
    this.$emit('fn1', '触发父组件第一个函数')
  },
}
</script>

image-20220804140705600.png

另外说个其他的小 tips

  • 没有被 父组件传递给子组件的值,如果没有被 props 接受。 默认会展示在 html 的标签上

image-20220804141342722.png

可使用 inheritAttrs: false, 隐藏