关于uni app vue2 和vue3 的区别
UniApp 中 Vue2 和 Vue3 的写法差异,核心源于 Vue 自身的 Options API(Vue2) 和 Composition API(Vue3) 设计理念的不同,同时结合 UniApp 框架的适配细节,以下从核心维度梳理最关键的区别,附清晰示例和对比表,方便快速对照:
一、核心语法结构:Options API vs Composition API
这是最根本的差异------Vue2 按「选项」组织代码,Vue3 按「逻辑」聚合代码(推荐 <script setup> 语法糖)。
| 维度 | Vue2(UniApp) | Vue3(UniApp) |
|---|---|---|
| 脚本结构 | 导出包含 data/methods/watch 等选项的对象 |
<script setup> 直接写逻辑(无需导出) |
| 数据响应式 | data() 返回对象,基于 Object.defineProperty |
ref/reactive 声明,基于 Proxy |
| 方法定义 | methods 选项内声明函数 |
直接在 <script setup> 定义函数 |
this 指向 |
可通过 this 访问数据/方法/API |
无 this(ref 需 .value,API 直接调用) |
示例:基础页面对比
Vue2 写法(Options API)
vue
<template>
<view>{{ msg }} - {{ doubleCount }}</view>
<button @click="add">+1</button>
</template>
<script>
export default {
name: 'Vue2Page',
// 响应式数据
data() {
return {
msg: 'Vue2 示例',
count: 0
}
},
// 计算属性
computed: {
doubleCount() {
return this.count * 2
}
},
// 方法
methods: {
add() {
this.count++
this.$uni.showToast({ title: '计数+1' }) // this 调用 UniApp API
}
},
// 页面生命周期
onLoad() {
console.log('页面加载')
}
}
</script>
Vue3 写法(<script setup>)
vue
<template>
<view>{{ msg }} - {{ doubleCount }}</view>
<button @click="add">+1</button>
</template>
<script setup>
// 1. 导入 Vue 核心 API
import { ref, computed } from 'vue'
// 2. 直接声明响应式数据(基础类型用 ref)
const msg = ref('Vue3 示例')
const count = ref(0)
// 3. 计算属性(函数式)
const doubleCount = computed(() => count.value * 2) // ref 需 .value
// 4. 方法直接定义
const add = () => {
count.value++
uni.showToast({ title: '计数+1' }) // 无 this,直接调用 uni API
}
// 5. 页面生命周期直接调用
onLoad(() => {
console.log('页面加载')
})
</script>
二、生命周期:命名与使用方式
1. UniApp 页面生命周期(如 onLoad/onShow)
- Vue2:写在组件选项中;
- Vue3:
<script setup>中直接调用(无需导入,UniApp 内置); - ✅ 名称完全一致,仅写法不同。
2. Vue 组件生命周期(原生)
Vue3 重命名了部分钩子,且需导入使用(无 this 绑定):
| Vue2 钩子 | Vue3 替代方案 | 说明 |
|---|---|---|
beforeCreate |
setup 内代码 |
无需单独声明 |
created |
setup 内代码 |
无需单独声明 |
beforeMount |
onBeforeMount(需导入) |
前缀加 on |
mounted |
onMounted(需导入) |
同上 |
beforeDestroy |
onBeforeUnmount(导入) |
重命名(语义更清晰) |
destroyed |
onUnmounted(导入) |
重命名 |
Vue3 组件生命周期示例
vue
<script setup>
import { onMounted, onUnmounted } from 'vue'
onMounted(() => {
console.log('组件挂载完成')
})
onUnmounted(() => {
console.log('组件卸载')
})
</script>
三、响应式数据:定义与修改
Vue2 响应式有局限性,Vue3 基于 Proxy 彻底解决,且写法更灵活:
| 场景 | Vue2 写法 | Vue3 写法 |
|---|---|---|
| 基础类型数据 | data() { return { num: 0 } } |
const num = ref(0) |
| 引用类型数据 | data() { return { obj: { name: 'test' } } } |
const obj = reactive({ name: 'test' }) |
| 修改基础类型 | this.num = 10 |
num.value = 10(模板中无需 .value) |
| 新增对象属性 | this.$set(this.obj, 'age', 20)(必须) |
obj.age = 20(天然支持) |
| 修改数组索引 | this.$set(this.arr, 0, 100)(必须) |
arr[0] = 100(天然支持) |
四、组件通信:Props/Emits
Vue3 新增 defineProps/defineEmits 语法糖(无需导入),更简洁且类型友好:
1. Props 接收
Vue2
javascript
export default {
props: {
title: {
type: String,
default: '默认标题'
}
},
mounted() {
console.log(this.title) // 通过 this 访问
}
}
Vue3
vue
<script setup>
// 声明 Props
const props = defineProps({
title: {
type: String,
default: '默认标题'
}
})
// 直接访问(无 this)
console.log(props.title)
</script>
2. 自定义事件(Emits)
Vue2
javascript
export default {
methods: {
handleClick() {
this.$emit('submit', { id: 1 }) // 直接 emit
}
}
}
Vue3
vue
<script setup>
// 声明事件(推荐)
const emit = defineEmits(['submit'])
const handleClick = () => {
emit('submit', { id: 1 }) // 调用 emit 方法
}
</script>
五、其他关键差异
| 功能 | Vue2 写法 | Vue3 写法 |
|---|---|---|
| 过滤器(Filter) | 支持 filters 选项 |
移除,用计算属性/函数替代 |
| 全局 API 挂载 | Vue.prototype.$api = api |
app.config.globalProperties.$api = api |
| 监听属性 | watch 选项(支持 deep/immediate) |
watch/watchEffect 函数(需导入) |
| 插槽 | slot/slot-scope 指令 |
统一用 v-slot(缩写 #) |
| 异步组件 | component: () => import('./xxx.vue') |
defineAsyncComponent(() => import('./xxx.vue')) |
六、UniApp 特有 API 调用
-
Vue2:
this.$uni.showToast()或uni.showToast(); -
Vue3:仅支持
uni.showToast()(无this,无法用this.$uni),也可按需导入:javascriptimport { showToast } from '@dcloudio/uni-app' showToast({ title: '提示' })
七、核心差异总结表
| 维度 | Vue2(UniApp) | Vue3(UniApp) |
|---|---|---|
| 核心范式 | Options API(选项式) | Composition API(组合式) |
| 脚本标识 | export default {} |
<script setup> |
| 响应式 | data() + $set |
ref/reactive(无需 $set) |
| this 绑定 | 依赖 this 访问所有内容 | 无 this,直接访问变量/函数 |
| 生命周期 | 选项式声明 | 函数式调用(部分重命名) |
| 组件通信 | this.$props/this.$emit |
defineProps/defineEmits |
| 过滤器 | 支持 | 移除(用计算属性替代) |
迁移建议
- 优先使用
<script setup>语法糖,简化代码; - 响应式数据统一用
ref(基础类型)/reactive(引用类型); - 生命周期替换为 Vue3 版本(如
mounted→onMounted); - 抛弃
filters,改用计算属性/函数; - 全局 API 挂载调整为
app.config.globalProperties。
Vue3 在 UniApp 中的写法更灵活、响应式能力更强,核心是从「按选项组织代码」转向「按逻辑聚合代码」,UniApp 底层已完全兼容,迁移成本主要在语法习惯调整。