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. 性能优化

    • 合理使用响应式数据
    • 避免不必要的组件通信
    • 及时清理事件监听器
相关推荐
@大迁世界18 分钟前
React Native 0.77 发布:更强的样式支持与性能优化
javascript·react native·react.js·ecmascript
NiNg_1_23419 分钟前
使用CSS实现一个加载的进度条
前端·css·进度条
CaptainDrake1 小时前
React 低代码项目:项目创建
前端·react.js·低代码
我的青春不太冷1 小时前
深入探讨:服务器如何响应前端请求及后端如何查看前端提交的数据(基础语法版)
服务器·前端·状态模式
qq_544329173 小时前
CRM项目的开发与调试整体策略
前端·后端·bug
Y编程小白3 小时前
ECMAScript 6语法
前端·javascript·ecmascript
不写八个6 小时前
Vue3.0教程004:ref和reactive对比
前端·javascript·vue.js
梅羽落8 小时前
JavaScript_03 超简计算器
前端·javascript
ChinaRainbowSea9 小时前
四.4 Redis 五大数据类型/结构的详细说明/详细使用( zset 有序集合数据类型详解和使用)
java·javascript·数据库·redis·后端·nosql
前端 贾公子9 小时前
axios如何利用promise无痛刷新token
前端