企业项目管理、ORK、研发管理与敏捷开发工具平台

网站首页 > 精选文章 正文

Vue2和Vue3 区别

wudianyun 2025-02-27 16:57:45 精选文章 42 ℃

从 Vue2 到 Vue3:一个老Vue开发者的升级指南

最近和前端同事交流发现在 vue3 的项目中还是惯性的使用 vue2 的选项式写法。这篇文章将从实践角度分享我的学习心得,希望能帮助同样准备升级的你。

为什么要升级到 Vue3?

在开始之前,我们先聊聊为什么要升级到 Vue3:

  1. 更好的性能:Vue3 的虚拟 DOM 重写和 Tree-shaking 支持带来了更好的性能
  2. 组合式 API:解决了 Vue2 中组件逻辑复用的痛点
  3. 更好的 TypeScript 支持:Vue3 是用 TypeScript 重写的,提供了更好的类型推导
  4. 更小的包体积:得益于 Tree-shaking,你可以只打包用到的功能

快速上手指南

1. 创建应用的新方式

如果你习惯了 Vue2 的写法:

// Vue2 的写法
import Vue from 'vue'
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

在 Vue3 中变成了:

// Vue3 的写法
import { createApp } from 'vue'
const app = createApp(App)
app.use(router)
app.use(store)
app.mount('#app')

个人感受:这种改变实际上更符合直觉,创建应用然后挂载插件的方式更加线性和清晰。

2. 响应式系统的变化

在 Vue2 中,我们习惯了直接在 data 中定义数据:

// Vue2
export default {
  data() {
    return {
      count: 0,
      user: {
        name: '张三',
        age: 25
      }
    }
  }
}

Vue3 中需要使用 ref 或 reactive:

// Vue3



个人最佳实践:

  • 优先使用 ref,因为它可以包装任何值
  • 只在确实需要对象响应式的场景使用 reactive
  • 记住在 JS 中需要用 .value 访问 ref 的值

3. 组合式 API 介绍

在 Vue3 中,我们可以用 Composition API 重写:

// Vue3 的 组合式 API

为什么我推荐 Composition API:

  1. 相关逻辑可以组织在一起,不再需要在 data、methods、computed 之间来回跳转
  2. 更好的代码复用能力,可以轻松提取和复用逻辑
  3. 更好的类型推导支持

4. 模板语法的变化

Vue3 在模板语法方面保持了大部分与 Vue2 的兼容性,但有一些值得注意的改进:






主要改进:

  • 支持多根节点模板
  • v-for 和 v-if 优先级更明确
  • 更好的 TypeScript 支持
  • 更好的性能优化

5. 生命周期的变化

Vue2 的生命周期钩子都有对应的 Vue3 版本,只是需要手动导入:

// Vue3
import { 
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted 
} from 'vue'

// 使用方式
onMounted(() => {
  console.log('组件已挂载')
})

注意:

  • beforeCreate 和 created 钩子在 setup 中是不需要的,因为 setup 本身就是在这两个钩子之间执行
  • destroyed 改名为 unmounted
  • beforeDestroy 改名为 beforeUnmount

6. 计算属性的使用

计算属性在 Vue3 中的写法更加简洁:

// Vue2
export default {
  data() {
    return {
      firstName: '张',
      lastName: '三'
    }
  },
  computed: {
    // 只读计算属性
    fullName() {
      return this.firstName + this.lastName
    },
    // 可写计算属性
    fullNameWithSetter: {
      get() {
        return this.firstName + this.lastName
      },
      set(newValue) {
        [this.firstName, this.lastName] = newValue.split(' ')
      }
    }
  }
}

// Vue3

7. 监听器的改进

Vue3 的 watch 和 watchEffect 提供了更强大的监听能力:

// Vue2
export default {
  data() {
    return {
      name: '',
      userInfo: {
        age: 25
      }
    }
  },
  watch: {
    // 监听简单属性
    name(newVal, oldVal) {
      console.log('name changed:', newVal, oldVal)
    },
    // 监听对象属性
    'userInfo.age': {
      handler(newVal, oldVal) {
        console.log('age changed:', newVal, oldVal)
      },
      deep: true,
      immediate: true
    }
  }
}

// Vue3

8. Props 和 Emits 的声明

Vue3 提供了更明确的 Props 和 Emits 声明方式:

// Vue2
export default {
  props: {
    title: {
      type: String,
      required: true,
      default: ''
    }
  },
  methods: {
    handleClick() {
      this.$emit('update', { value: 'newValue' })
    }
  }
}

// Vue3




Props 和 Emits 的主要改进:

  • 更好的类型推导
  • 运行时验证
  • 更清晰的事件类型定义
  • 可以使用 TypeScript 的类型标注

9. 插槽(Slots)的使用变化

// Vue2


// Vue3




  
  
  
  

10. Teleport 组件

Vue3 新增了 Teleport 组件,可以将内容渲染到 DOM 的其他位置:



11. 异步组件的改进

// Vue2
const AsyncComp = () => ({
  component: import('./AsyncComp.vue'),
  loading: LoadingComponent,
  error: ErrorComponent,
  delay: 200,
  timeout: 3000
})

// Vue3
import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent({
  loader: () => import('./AsyncComp.vue'),
  loadingComponent: LoadingComponent,
  errorComponent: ErrorComponent,
  delay: 200,
  timeout: 3000
})

// 简写方式
const AsyncComp = defineAsyncComponent(() => import('./AsyncComp.vue'))

12. 全局 API 的改变

// Vue2
import Vue from 'vue'

Vue.config.ignoredElements = [/^app-/]
Vue.use(/* ... */)
Vue.mixin(/* ... */)
Vue.component(/* ... */)
Vue.directive(/* ... */)

// Vue3
import { createApp } from 'vue'
const app = createApp(App)

app.config.compilerOptions.isCustomElement = tag => tag.startsWith('app-')
app.use(/* ... */)
app.mixin(/* ... */)
app.component(/* ... */)
app.directive(/* ... */)

13. 自定义指令的变化

// Vue2
Vue.directive('highlight', {
  bind(el, binding) {},
  inserted(el, binding) {},
  update(el, binding) {},
  componentUpdated(el, binding) {},
  unbind(el, binding) {}
})

// Vue3
app.directive('highlight', {
  beforeMount(el, binding) {}, // 替代 bind
  mounted(el, binding) {},     // 替代 inserted
  beforeUpdate(el, binding) {}, // 新增
  updated(el, binding) {},     // 替代 update + componentUpdated
  beforeUnmount(el, binding) {}, // 新增
  unmounted(el, binding) {}    // 替代 unbind
})

14. 过渡动画的变化



  

hello

hello

主要变化:

  • 过渡类名改变:v-enter 改为 v-enter-from
  • 组件名称大写:transition 改为 Transition
  • 新增 persisted 钩子用于处理缓存组件的过渡

性能优化的改进

Vue3 在性能方面有显著提升:

  1. 更好的 Tree-shaking 支持
  2. 按需引入 API
  3. 更小的打包体积
  4. Fragment 支持
  5. 不再需要根节点包裹
  6. 减少 DOM 层级
  7. 静态提升
  8. 静态节点被提升到渲染函数之外
  9. 减少重复创建开销
  10. Proxy 响应式系统
  11. 更好的性能
  12. 更完善的响应式支持

升级建议

  1. 渐进式迁移
  2. 新功能用 Vue3 + Composition API
  3. 老项目可以继续使用 Options API,Vue3 完全兼容
  4. 随着对 Composition API 的熟悉,逐步重构老代码
  5. 使用
最近发表
标签列表