vue2和vue3组件之间的通信方式差异

Vue2 vs Vue3 组件通信方法对比

1. 父子组件通信

1.1 Props 传递

Vue2

vue 复制代码
<!-- 父组件 -->
<template>
  <child-component :message="message"></child-component>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello'
    }
  }
}
</script>

<!-- 子组件 -->
<script>
export default {
  props: {
    message: String
  }
}
</script>

Vue3

vue 复制代码
<!-- 父组件 -->
<template>
  <child-component :message="message"></child-component>
</template>

<script setup>
import { ref } from 'vue'
const message = ref('Hello')
</script>

<!-- 子组件 -->
<script setup>
defineProps({
  message: String
})
</script>

1.2 自定义事件

Vue2

vue 复制代码
<!-- 子组件 -->
<template>
  <button @click="handleClick">点击</button>
</template>

<script>
export default {
  methods: {
    handleClick() {
      this.$emit('custom-event', { data: 'value' })
    }
  }
}
</script>

<!-- 父组件 -->
<template>
  <child @custom-event="handleEvent"></child>
</template>

<script>
export default {
  methods: {
    handleEvent(data) {
      console.log(data)
    }
  }
}
</script>

Vue3

vue 复制代码
<!-- 子组件 -->
<template>
  <button @click="handleClick">点击</button>
</template>

<script setup>
const emit = defineEmits(['custom-event'])

const handleClick = () => {
  emit('custom-event', { data: 'value' })
}
</script>

<!-- 父组件 -->
<template>
  <child @custom-event="handleEvent"></child>
</template>

<script setup>
const handleEvent = (data) => {
  console.log(data)
}
</script>

2. 跨层级组件通信

2.1 provide/inject

Vue2

vue 复制代码
<!-- 祖先组件 -->
<script>
export default {
  provide() {
    return {
      theme: this.theme,
      updateTheme: this.updateTheme
    }
  },
  data() {
    return {
      theme: 'dark'
    }
  },
  methods: {
    updateTheme(value) {
      this.theme = value
    }
  }
}
</script>

<!-- 后代组件 -->
<script>
export default {
  inject: ['theme', 'updateTheme']
}
</script>

Vue3

vue 复制代码
<!-- 祖先组件 -->
<script setup>
import { provide, ref } from 'vue'

const theme = ref('dark')
const updateTheme = (value) => {
  theme.value = value
}

provide('theme', {
  theme,
  updateTheme
})
</script>

<!-- 后代组件 -->
<script setup>
import { inject } from 'vue'

const { theme, updateTheme } = inject('theme')
</script>

2.2 事件总线

Vue2

javascript 复制代码
// eventBus.js
import Vue from 'vue'
export const eventBus = new Vue()

// 组件 A
this.eventBus.$emit('custom-event', data)

// 组件 B
mounted() {
  this.eventBus.$on('custom-event', this.handleEvent)
},
beforeDestroy() {
  this.eventBus.$off('custom-event', this.handleEvent)
}

Vue3

typescript 复制代码
// eventBus.ts
import mitt from 'mitt'
export const emitter = mitt()

// 组件 A
import { emitter } from './eventBus'
emitter.emit('custom-event', data)

// 组件 B
import { onMounted, onUnmounted } from 'vue'
import { emitter } from './eventBus'

onMounted(() => {
  emitter.on('custom-event', handleEvent)
})

onUnmounted(() => {
  emitter.off('custom-event', handleEvent)
})

3. 访问组件实例

3.1 ref 引用

Vue2

vue 复制代码
<!-- 父组件 -->
<template>
  <child-component ref="childRef"></child-component>
</template>

<script>
export default {
  mounted() {
    console.log(this.$refs.childRef.someData)
    this.$refs.childRef.someMethod()
  }
}
</script>

<!-- 子组件 -->
<script>
export default {
  data() {
    return {
      someData: 'value'
    }
  },
  methods: {
    someMethod() {
      // ...
    }
  }
}
</script>

Vue3

vue 复制代码
<!-- 父组件 -->
<template>
  <child-component ref="childRef"></child-component>
</template>

<script setup>
import { ref, onMounted } from 'vue'

const childRef = ref(null)

onMounted(() => {
  console.log(childRef.value.someData)
  childRef.value.someMethod()
})
</script>

<!-- 子组件 -->
<script setup>
import { ref } from 'vue'

const someData = ref('value')
const someMethod = () => {
  // ...
}

defineExpose({
  someData,
  someMethod
})
</script>

3.2 父组件访问

Vue2

vue 复制代码
<!-- 子组件 -->
<script>
export default {
  methods: {
    accessParent() {
      console.log(this.$parent.parentData)
      this.$parent.parentMethod()
    }
  }
}
</script>

Vue3

vue 复制代码
<!-- 子组件 -->
<script setup>
import { getCurrentInstance } from 'vue'

const { proxy } = getCurrentInstance()
const accessParent = () => {
  console.log(proxy.$parent.parentData)
  proxy.$parent.parentMethod()
}
</script>

4. 主要差异总结

  1. 语法差异

    • Vue2 使用选项式 API
    • Vue3 推荐使用组合式 API 和 <script setup>
  2. 事件总线

    • Vue2 可以使用 Vue 实例作为事件总线
    • Vue3 移除了 on, off 等方法,需要使用第三方库(如 mitt)
  3. 组件实例访问

    • Vue2 可以直接访问组件实例的所有属性和方法
    • Vue3 需要通过 defineExpose 显式暴露要访问的属性和方法
  4. 响应式系统

    • Vue2 使用 Object.defineProperty
    • Vue3 使用 Proxy,提供了更好的响应式支持
  5. 性能优化

    • Vue3 提供了更好的性能优化机制
    • 组件通信的性能开销更小

5. 最佳实践建议

  1. 迁移策略

    • 逐步从 Vue2 迁移到 Vue3
    • 优先使用 Vue3 的新特性
    • 保持代码的一致性
  2. 代码组织

    • Vue3 中更推荐使用组合式 API
    • 将相关的逻辑组织在一起
    • 使用 hooks 复用逻辑
  3. 性能优化

    • 合理使用响应式数据
    • 避免不必要的组件通信
    • 及时清理事件监听器
相关推荐
一个游离的指针27 分钟前
ES6基础特性
前端·javascript·es6
layman052828 分钟前
ES6/ES11知识点
前端·ecmascript·es6
2501_915373885 小时前
Vue 3零基础入门:从环境搭建到第一个组件
前端·javascript·vue.js
沙振宇8 小时前
【Web】使用Vue3开发鸿蒙的HelloWorld!
前端·华为·harmonyos
运维@小兵8 小时前
vue开发用户注册功能
前端·javascript·vue.js
蓝婷儿8 小时前
前端面试每日三题 - Day 30
前端·面试·职场和发展
oMMh9 小时前
使用C# ASP.NET创建一个可以由服务端推送信息至客户端的WEB应用(2)
前端·c#·asp.net
一口一个橘子9 小时前
[ctfshow web入门] web69
前端·web安全·网络安全
读心悦10 小时前
CSS:盒子阴影与渐变完全解析:从基础语法到创意应用
前端·css
m0_6161884910 小时前
使用vue3-seamless-scroll实现列表自动滚动播放
开发语言·javascript·ecmascript