vue3和vue2父子组件互相通信的方式和原理

一、背景介绍

在Vue框架中,父子组件之间的数据传递是一个核心功能,它允许组件之间进行有效的通信和数据共享。随着Vue 3的发布,父子组件之间的传值方式发生了一些变化,同时也带来了一些新的特性和改进。本文将详细总结Vue 3与Vue 2在父子组件传值方面的区别和原理。

二、Vue 2父子组件传值

在Vue 2中,父子组件之间的数据传递主要依赖props和自定义事件。

父传子(Props)‌:
  • 父组件通过属性(attributes)的方式将数据传递给子组件。

  • 子组件通过props接收这些数据。

  • 数据是单向流动的,子组件不能直接修改父组件传递的数据。

  • 具体使用:

<!-- Vue 2 父组件 -->
<template>
  <div>
    <child-component :message="parentMessage"></child-component>
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      parentMessage: 'Hello from parent'
    };
  }
};
</script>

<!-- Vue 2 子组件 -->
<template>
  <div>{{ message }}</div>
</template>

<script>
export default {
  props: ['message']
};
</script>
子传父(自定义事件)‌:
  • 子组件通过this.$emit方法触发自定义事件,并将数据作为参数传递给父组件。

  • 父组件通过监听这些自定义事件来接收子组件传递的数据。

  • 具体使用:

    <!-- Vue 2 父组件 -->
    <template>
      <div>
        <child-component @childEvent="handleChildEvent"></child-component>
      </div>
    </template>
    
    <script>
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      components: {
        ChildComponent
      },
      methods: {
        handleChildEvent(message) {
          console.log('Message from child:', message);
        }
      }
    };
    </script>
    
    
    <!-- Vue 2 子组件 -->
    <template>
      <div>
        <button @click="emitEvent">Emit Event</button>
      </div>
    </template>
    
    <script>
    export default {
      methods: {
        emitEvent() {
          this.$emit('childEvent', 'Hello from child');
        }
      }
    };
    </script>
    父调用子方法‌:
  • 父组件通过ref引用子组件实例,然后直接调用子组件的方法

  • 具体使用:

    <!-- Vue 2 父组件 -->
    <template>
      <div>
        <child-component ref="childRef"></child-component>
        <button @click="callChildMethod">Call Child Method</button>
      </div>
    </template>
    
    <script>
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      components: {
        ChildComponent
      },
      methods: {
        callChildMethod() {
          this.$refs.childRef.childMethod();
        }
      }
    };
    </script>
    
    
    <!-- Vue 2 子组件 -->
    <template>
      <div>Child Component</div>
    </template>
    
    <script>
    export default {
      methods: {
        childMethod() {
          console.log('Child method called');
        }
      }
    };
    </script>

三、Vue 3父子组件传值

Vue 3在保持Vue 2核心传值机制的基础上,引入了Composition API,并对父子组件之间的传值与调用方法进行了优化和改进。

父传子(Props)‌:
  • 父组件通过属性(attributes)的方式将数据传递给子组件的方式没有改变。

  • 子组件通过defineProps(在<script setup>中)或props选项(在<script>中)接收数据。

  • Vue 3中的defineProps提供了一种更简洁的方式来定义和接收props

  • 具体使用:

    <!-- Vue 3 父组件 -->
    <template>
      <ChildComponent :message="parentMessage" />
    </template>
    
    <script>
    import { ref } from 'vue';
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      components: {
        ChildComponent
      },
      setup() {
        const parentMessage = ref('Hello from parent');
        return { parentMessage };
      }
    };
    </script>
    
    <!-- Vue 3 子组件 -->
    <template>
      <div>{{ message }}</div>
    </template>
    
    <script setup>
    import { defineProps } from 'vue';
    const props = defineProps({
      message: {
        type: String,
        required: true
      }
    });
    </script>
子传父(自定义事件)‌:
  • 子组件通过defineEmits(在<script setup>中)或$emit方法触发自定义事件。

  • Vue 3中的defineEmits提供了一种更简洁的方式来定义和触发自定义事件。

  • 父组件通过监听这些自定义事件来接收子组件传递的数据的方式没有改变。

  • 具体使用:

    <!-- Vue 3 父组件 -->
    <template>
      <ChildComponent @childEvent="handleChildEvent" />
    </template>
    
    <script>
    import { ref } from 'vue';
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      components: {
        ChildComponent
      },
      setup() {
        const handleChildEvent = (message) => {
          console.log('Message from child:', message);
        };
        return { handleChildEvent };
      }
    };
    </script>
    
    <!-- Vue 3 子组件 -->
    <template>
      <div>
        <button @click="emitEvent">Emit Event</button>
      </div>
    </template>
    
    <script setup>
    import { defineEmits } from 'vue';
    const emit = defineEmits(['childEvent']);
    
    const emitEvent = () => {
      emit('childEvent', 'Hello from child');
    };
    </script>
    
    父调用子方法‌:
  • 父组件通过ref引用子组件实例,然后直接调用子组件的方法。

  • Vue 3中的refreactive等响应式API提供了更灵活的组件状态管理。

  • 在Vue 3中,defineExpose方法用于显式地声明子组件中哪些方法或属性应该被父组件访问,这有助于避免不必要的属性暴露,提高组件的封装性。

  • 具体使用:

    <!-- Vue 3 父组件 -->
    <template>
      <div>
        <ChildComponent ref="childRef" />
        <button @click="callChildMethod">Call Child Method</button>
      </div>
    </template>
    
    <script>
    import { ref } from 'vue';
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      components: {
        ChildComponent
      },
      setup() {
        const childRef = ref(null);
        const callChildMethod = () => {
          if (childRef.value) {
            childRef.value.childMethod();
          }
        };
        return { childRef, callChildMethod };
      }
    };
    </script>
    
    
     <!-- Vue 3 子组件 -->
    <template>
      <div>Child Component</div>
    </template>
    
    <script setup>
    import { defineExpose } from 'vue';
    
    const childMethod = () => {
      console.log('Child method called');
    };
    
    defineExpose({ childMethod });
    </script>

四、区别与原理

1.API差异‌:
  • Vue 2使用props选项来接收数据,使用this.$emit来触发事件。

  • Vue 3引入了Composition API,提供了definePropsdefineEmits来更简洁地处理props和自定义事件。

2.响应式系统‌:
  • Vue 2使用Object.defineProperty来实现响应式数据绑定。

  • Vue 3使用Proxy对象来实现更高效的响应式数据绑定,这在一定程度上影响了父子组件之间数据传递的性能和灵活性。

‌3.组件通信的灵活性‌:
  • Vue 3通过引入provideinject机制,允许跨层级的组件通信,这在处理复杂组件树时非常有用。

  • 在Vue 2中,跨层级的组件通信通常需要使用事件总线(Event Bus)或Vuex等状态管理库来实现。

4.TypeScript支持‌:
  • Vue 3对TypeScript提供了更好的支持,definePropsdefineEmits可以与TypeScript的类型系统紧密结合,提供更强的类型检查和代码提示。

五、结论

Vue 3在父子组件传值方面保留了Vue 2的核心机制,同时引入了一些新的特性和改进,使得组件之间的通信更加灵活和高效。随着Composition API的引入,Vue 3的API设计更加简洁和直观,同时也为TypeScript用户提供了更好的支持。无论是Vue 2还是Vue 3,父子组件之间的数据传递都是构建复杂Vue应用的基础,理解其原理和差异对于开发者来说至关重要。

### Vue3父子组件通过 `defineProps` 进行通信Vue3 的组合式 API 中,`defineProps` 是一种用于定义子组件接收父组件递数据的方法。它允许开发者声明 props 并指定其类型其他约束条件[^2]。 #### 父组件向子组件示例 以下是父组件向子组件递数据的具体实现: ##### 父组件代码 ```vue <template> <div> <h1>父组件</h1> <ChildComponent :message="parentMessage" /> </div> </template> <script setup> import ChildComponent from &#39;./ChildComponent.vue&#39;; const parentMessage = &#39;这是来自父组件的消息&#39;; </script> ``` 在此代码中,父组件通过属性绑定的方式 (`:message`) 将变量 `parentMessage` 的递给子组件[^1]。 ##### 子组件代码 ```vue <template> <div> <p>{{ message }}</p> </div> </template> <script setup> // 定义 Props 接收父组件的数据 const props = defineProps({ message: { type: String, required: true, // 表明此 prop 是必需的 } }); </script> ``` 在这个例子中,子组件使用了 `defineProps` 方法来声明一个名为 `message` 的 prop,并指定了它的类型为字符串以及它是必需的。 --- ### 关键点解析 - **`defineProps` 的作用** `defineProps` 是 Vue3 提供的一个宏,在 `<script setup>` 中无需导入即可直接使用。它可以用来定义子组件接收到的 props 数据结构及其验证规则。 - **Prop 验证规则** 开发者可以通过对象形式为每个 prop 设置详细的验证规则,例如类型、默认是否必填等。 --- ### 总结 通过上述方式,可以轻松实现父组件向子组件递数据的功能。父组件只需将所需数据作为属性绑定到子组件上,而子组件则利用 `defineProps` 来接收并处理这些数据。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值