父子组件通信

 前端   大苹果   2024-09-17 10:12   11

在 Vue 3 中,setup 函数是 Vue 3 中的 Composition API 的核心,它提供了一种更灵活的方式来定义组件逻辑。propsemit 是父子组件通信的基础,通过 setup 函数,这些机制得到了更简化的实现。Vue 3 中的 emits 事件管理也变得更加结构化。

一、setup 下的 propsemit

setup 函数中,props 是以参数的形式传递给组件,而 emit 事件函数也是通过参数获取的。我们来看看如何使用它们。

1. 父组件传递 props

在 Vue 3 中,父组件通过 props 向子组件传递数据的方式没有改变,仍然是在子组件标签上使用绑定的方式传递数据。

父组件代码:

<template>
  <div>
    <h1>父组件</h1>
    <ChildComponent :message="parentMessage" :count="parentCount" @child-event="handleChildEvent"></ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
  data() {
    return {
      parentMessage: 'Hello from parent!',
      parentCount: 10
    };
  },
  methods: {
    handleChildEvent(payload) {
      console.log('父组件接收到的子组件事件数据:', payload);
    }
  }
};
</script>

在这个例子中,父组件传递了 messagecount 给子组件。

2. 子组件接收 props 和触发 emit

setup 函数中,propsemit 通过参数接收。emit 可以触发自定义事件,将数据传递给父组件。

子组件代码:

<template>
  <div>
    <h2>子组件</h2>
    <p>Message from parent: {{ message }}</p>
    <p>Count from parent: {{ count }}</p>
    <button @click="sendMessage">向父组件发送事件</button>
  </div>
</template>

<script>
import { defineComponent } from 'vue';

export default defineComponent({
  props: {
    message: String,
    count: Number,
  },
  setup(props, { emit }) {
    const sendMessage = () => {
      emit('child-event', 'Hello from Child');
    };

    return { props, sendMessage };
  }
});
</script>

setup 函数中,我们通过参数接收了 props,并定义了一个 sendMessage 函数,通过 emit 触发自定义事件 child-event,将数据传递给父组件。

二、emits 事件管理

在 Vue 3 中,emits 选项允许我们显式地定义子组件会触发哪些事件,这是一种增强的事件管理方式。

1. emits 选项

在子组件中,我们可以通过 emits 选项来定义组件可以触发的事件。这样做的好处是,可以对事件进行更好的文档化和管理,也可以对事件触发进行校验。

<script>
import { defineComponent } from 'vue';

export default defineComponent({
  props: {
    message: String,
    count: Number,
  },
  emits: ['child-event'],  // 定义子组件将会触发的事件
  setup(props, { emit }) {
    const sendMessage = () => {
      emit('child-event', 'Hello from Child');  // 触发事件
    };

    return { props, sendMessage };
  }
});
</script>

2. 事件校验

emits 选项不仅能定义事件,还可以为事件添加校验逻辑。我们可以通过函数校验事件的参数是否符合预期。

<script>
import { defineComponent } from 'vue';

export default defineComponent({
  props: {
    message: String,
    count: Number,
  },
  emits: {
    'child-event': (payload) => {
      return typeof payload === 'string';  // 校验事件参数必须是字符串
    }
  },
  setup(props, { emit }) {
    const sendMessage = () => {
      emit('child-event', 'Hello from Child');
    };

    return { props, sendMessage };
  }
});
</script>

在这个示例中,emits 选项中为 child-event 事件定义了一个校验函数,只有当事件参数是字符串时,事件才会被触发。

三、setup 下的原理解析

1. props 原理

setup 中接收的 props 是响应式的,这意味着当父组件传递的 props 数据变化时,子组件会自动更新。

  • setup 中接收到的 props 是不可直接解构的,否则将失去响应式能力。如果需要解构,可以使用 toRefstoRef
import { toRefs } from 'vue';

setup(props) {
  const { message, count } = toRefs(props);  // 解构成响应式变量
  return { message, count };
}

2. emit 原理

emit 函数是 Vue 内置的事件触发机制,它允许组件触发自定义事件,并将数据传递给父组件。Vue 内部会根据 emits 选项确保事件是有效的并调用父组件的监听器。

四、示例:父子组件通信

我们通过一个简单的例子,展示 propsemitsetup 下的具体应用。

父组件:

<template>
  <div>
    <h1>父组件</h1>
    <p>Count: {{ parentCount }}</p>
    <ChildComponent :count="parentCount" @update-count="handleUpdateCount"></ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
  data() {
    return {
      parentCount: 0
    };
  },
  methods: {
    handleUpdateCount(newCount) {
      this.parentCount = newCount;
    }
  }
};
</script>

子组件:

<template>
  <div>
    <h2>子组件</h2>
    <p>当前计数: {{ count }}</p>
    <button @click="increment">增加计数</button>
  </div>
</template>

<script>
import { defineComponent } from 'vue';

export default defineComponent({
  props: {
    count: Number,
  },
  emits: ['update-count'],
  setup(props, { emit }) {
    const increment = () => {
      emit('update-count', props.count + 1);
    };

    return { increment };
  }
});
</script>

总结

  1. propssetup 函数中 props 是通过参数传递的,不能直接解构,否则会丧失响应性。
  2. emitemit 函数可以触发事件,父组件通过监听子组件的自定义事件来实现双向数据交互。
  3. emits:在 Vue 3 中,可以通过 emits 选项来显式定义组件的事件,并且可以进行参数校验。

Vue 3 的 setupemits 机制使组件通信变得更加简洁和灵活,同时也增强了代码的可读性和可维护性。