Vue2 入门指南09:父子组件之间的通信

864 阅读3分钟

在 Vue 中,组件是应用程序的核心构建块。在实际开发中,父组件和子组件之间需要进行数据和事件的传递与交互。这种交互通常称为 父子组件通信。理解和掌握 Vue 中的父子组件通信方式是高效开发的关键。

在本篇文章中,我们将深入探讨 Vue2 中父子组件之间的通信方式,包括 Props事件.sync 修饰符 等。


一、父子组件通信:通过 Props 传递数据

Props 是 Vue 中父组件向子组件传递数据的主要方式。父组件通过 props 向子组件传递数据,而子组件则通过访问 props 来接收父组件传递的数据。

1. 父组件向子组件传递数据

<div id="app">
  <user-card :name="'张三'" :age="25"></user-card>
</div>

<script>
  Vue.component('user-card', {
    props: ['name', 'age'],
    template: '<div><p>姓名:{{ name }}</p><p>年龄:{{ age }}</p></div>'
  });

  new Vue({
    el: '#app'
  });
</script>

在上面的代码中,父组件通过 :name:age 向子组件 user-card 传递数据。子组件通过 props 选项接收这些数据,并在模板中渲染。

2. 使用默认值

你可以为 props 设置默认值,当父组件没有传递数据时,子组件会使用默认值。

<div id="app">
  <user-card></user-card>
</div>

<script>
  Vue.component('user-card', {
    props: {
      name: {
        type: String,
        default: '匿名用户'
      },
      age: {
        type: Number,
        default: 18
      }
    },
    template: '<div><p>姓名:{{ name }}</p><p>年龄:{{ age }}</p></div>'
  });

  new Vue({
    el: '#app'
  });
</script>

二、子组件向父组件通信:通过 $emit 触发事件

子组件通过 $emit 触发事件,将数据传递给父组件。这是 Vue 中子组件与父组件通信的标准方式。

1. 子组件触发事件

<div id="app">
  <counter @increment="handleIncrement"></counter>
  <p>当前计数:{{ count }}</p>
</div>

<script>
  Vue.component('counter', {
    template: '<button @click="increment">点击加 1</button>',
    methods: {
      increment() {
        // 使用 $emit 向父组件发送事件
        this.$emit('increment', 1);
      }
    }
  });

  new Vue({
    el: '#app',
    data: {
      count: 0
    },
    methods: {
      handleIncrement(value) {
        // 父组件接收到事件,更新数据
        this.count += value;
      }
    }
  });
</script>

在上面的代码中,子组件通过 $emit 触发了 increment 事件,并传递了一个值给父组件。父组件通过监听这个事件,并在 handleIncrement 方法中更新 count 值。


三、使用 .sync 修饰符进行双向绑定

Vue 允许通过 .sync 修饰符实现父子组件之间的数据双向绑定。通过这种方式,父组件可以直接修改子组件的 prop,实现更简便的通信。

1. 使用 .sync 修饰符

<div id="app">
  <user-card :name.sync="userName"></user-card>
  <p>当前用户名:{{ userName }}</p>
</div>

<script>
  Vue.component('user-card', {
    props: ['name'],
    template: '<div><input v-model="name" /></div>',
    watch: {
      name(newValue) {
        // 使用 $emit 更新父组件的值
        this.$emit('update:name', newValue);
      }
    }
  });

  new Vue({
    el: '#app',
    data: {
      userName: '张三'
    }
  });
</script>

在这个示例中,子组件通过 v-modelname prop 创建了双向绑定。当子组件内的 input 被修改时,name 的值会通过 update:name 事件传递回父组件,父组件的 userName 会自动更新。

使用 .sync 修饰符使得父组件的属性能够被子组件更方便地更新,而无需显式使用 $emit


四、动态绑定和事件的结合使用

在某些场景下,父子组件通信不仅仅局限于传递数据和触发事件,还涉及动态切换组件或事件处理器。你可以通过动态绑定来实现更复杂的交互。

1. 动态绑定 props 和事件处理

<div id="app">
  <user-card :name="userName" @change-name="changeUserName"></user-card>
  <p>当前用户名:{{ userName }}</p>
</div>

<script>
  Vue.component('user-card', {
    props: ['name'],
    template: '<div><button @click="changeName">修改名字</button></div>',
    methods: {
      changeName() {
        this.$emit('change-name', '李四');
      }
    }
  });

  new Vue({
    el: '#app',
    data: {
      userName: '张三'
    },
    methods: {
      changeUserName(newName) {
        this.userName = newName;
      }
    }
  });
</script>

在这个示例中,父组件通过 :name 向子组件传递用户名,并通过 @change-name 监听子组件触发的事件。当按钮点击时,子组件触发事件修改父组件的 userName 值。


五、使用 provideinject 进行跨层级传递

当父子组件的关系较深时,直接使用 props$emit 可能会造成繁琐的传递。Vue 提供了 provideinject 来简化这一过程。provide 用于父组件提供数据,inject 用于子组件获取数据。

1. 使用 provideinject

<div id="app">
  <grandparent></grandparent>
</div>

<script>
  Vue.component('grandparent', {
    provide() {
      return {
        sharedData: '我是祖先组件的数据'
      };
    },
    template: '<parent></parent>'
  });

  Vue.component('parent', {
    template: '<child></child>'
  });

  Vue.component('child', {
    inject: ['sharedData'],
    template: '<div>{{ sharedData }}</div>'
  });

  new Vue({
    el: '#app'
  });
</script>

在这个示例中,grandparent 组件通过 provide 提供了 sharedData 数据,child 组件通过 inject 获取了这个数据。这样,子组件可以跨层级访问父组件的数据,而无需通过层层传递 props


六、小结

在 Vue2 中,父子组件之间的通信是通过多种方式实现的,包括:

  • 使用 props 向子组件传递数据。
  • 使用 $emit 触发事件,让子组件向父组件发送数据。
  • 使用 .sync 修饰符简化双向绑定。
  • 使用 provideinject 实现跨层级传递数据。