作为一名熟悉 Vue 的开发者,当你第一次接触 uni-app 时,好消息是:你已经掌握了 uni-app 80% 的知识。uni-app 的核心就是 Vue 语法加上一套跨端编译机制。
但剩下的 20% 往往是新手踩坑的重灾区。这篇文章将用大白话,从底层原理到实战技巧,带你迅速跨越这 20% 的认知鸿沟,看完即可直接上手企业级项目。
一、 核心认知转换:你不再只写网页了
在写纯 Vue 时,你的代码运行在浏览器里,你可以肆无忌惮地操作 DOM(document.getElementById)、使用 BOM(window.location)。
但在 uni-app 中,你的代码可能要运行在微信小程序 或原生 App 中。 官方文档明确指出:App 和小程序的逻辑层和渲染层是分离的。
- 逻辑层:运行在独立的 JS 引擎中(App 上是 V8 或 JSCore,小程序是微信的 JS 引擎)。
- 渲染层:运行在 WebView 或原生渲染引擎(nvue/uts)中。
结论与习惯改变:
- 彻底戒掉 DOM/BOM 操作 :你的 JS 代码环境里压根没有
window和document。 - 数据驱动一切 :严格遵守 Vue 的响应式数据驱动视图理念。如果非要操作视图元素(比如获取节点高度),必须使用 uni-app 提供的
uni.createSelectorQuery()。
二、 主要的语法与开发差异
1. 标签(组件)的降维打击
在 Web 开发中,我们用 HTML 标签(div, span, img)。在 uni-app 中,为了兼容小程序和 App,必须使用基础组件(靠近微信小程序规范)。
<div>➡️<view><span>➡️<text><img>➡️<image>(注意:image 默认有宽高,不像 img 默认由内容撑开)<a>➡️<navigator>
2. 路由管理的剥离
Vue 开发者习惯用 vue-router。但在 uni-app 中,不需要也不建议使用 vue-router。 uni-app 采用类似小程序的路由配置方式:
- 配置 :所有页面必须在
pages.json中注册。 - 跳转 :使用
uni.navigateTo()、uni.redirectTo()、uni.switchTab()等 API,或者<navigator>标签。
php
// 伪代码对比
// Vue Router 跳转
router.push({ path: '/pages/detail', query: { id: 1 } })
// uni-app 跳转
uni.navigateTo({
url: '/pages/detail/detail?id=1'
})
3. 生命周期的"加戏"
除了 Vue 原生的生命周期(onMounted, onUnmounted 等),uni-app 引入了应用生命周期 和页面生命周期。
- 页面生命周期 :最常用的是
onLoad(options)(页面加载,接收路由参数)和onShow()(页面每次显示)。 - 注意点 :Vue 的
created/setup会在onLoad之前执行。建议初始化网络请求写在onLoad中 ,而不是onMounted,因为onLoad能直接拿到路由参数。
三、 API 与组件库选择
1. API 的替换
所有 Web 专属 API 都被 uni-app 重新封装成了跨端 API:
- 网络请求:
axios/fetch➡️uni.request() - 本地存储:
localStorage.setItem➡️uni.setStorageSync() - 弹窗提示:
alert/ElMessage➡️uni.showToast()/uni.showModal()
2. UI 组件库的断舍离
千万不要在 uni-app 中使用 Element Plus、Ant Design 等基于 DOM 的 Web UI 库! 它们在小程序和 App 中会直接报错。
推荐的跨端组件库:
- uni-ui:官方出品,最稳妥,兼容性最好,按需引入,体积小。
- uView Plus:目前生态最火的 Vue3 跨端组件库,功能极其丰富,适合快速外包和后台系统。
- ThorUI / GraceUI:部分收费,设计感较好。
四、 版本差异:Vue 与 uni-app 的恩怨情仇
1. Vue 2 vs Vue 3
uni-app 目前全面拥抱 Vue 3。
- Vue 2 版:底层基于 Webpack 编译。
- Vue 3 版 :底层基于 Vite 编译,编译速度极快(极度推荐)。
- 语法支持 :完全支持
<script setup>和 Composition API。
2. uni-app 自身的版本分支
- 普通 uni-app :写
.vue文件,编译到各端。 - uni-app x :DCloud 推出的下一代产品,使用 UTS 语言(强类型),在 App 端直接编译为 Kotlin/Swift,纯原生运行,没有 WebView。如果你刚入门,先学普通 uni-app,不要碰 uni-app x,生态还在建设中。
五、 跨端利器:条件编译(核心魔法)
这是 uni-app 最伟大的发明。当某个功能(比如微信支付、App 极光推送)无法跨端时,你可以用特殊注释让代码只在特定平台编译。
xml
<template>
<view>
<!-- #ifdef MP-WEIXIN -->
<button open-type="getPhoneNumber">只有微信小程序会编译这个按钮</button>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<button @click="appPay">只有原生 App 会编译这个按钮</button>
<!-- #endif -->
</view>
</template>
<script setup>
const login = () => {
// #ifdef H5
console.log('执行 H5 的网页登录逻辑')
// #endif
// #ifndef H5
console.log('除了 H5 之外的平台(小程序、App)都会执行这段代码')
// #endif
}
</script>
<style>
/* #ifdef MP-ALIPAY */
.box { background: blue; } /* 只在支付宝小程序生效 */
/* #endif */
</style>
六、 已知的坑与避坑指南(高价值经验)
-
逻辑层与渲染层的通讯瓶颈:
- 坑 :在 Vue 中,你把一个包含 10000 个对象的巨型数组绑定到视图上,可能只是稍微卡顿。但在 uni-app(小程序/App)中,数据需要从逻辑层(JS引擎)序列化后通过 Bridge 传递给渲染层(WebView)。传递巨型数据会直接导致页面卡死。
- 避坑 :视图不需要的数据(如复杂的内部状态),不要放在
ref或reactive中,直接用普通变量。长列表必须使用<scroll-view>或专门的虚拟列表组件。
-
CSS 作用域与深度选择器:
- 坑:小程序环境对 CSS 隔离非常严格。
- 避坑 :尽量每个组件都加
<style scoped>。修改子组件(如 uni-ui)样式时,Vue3 中使用:deep(.uni-card),但要注意某些小程序平台可能不支持过于复杂的深度选择器嵌套。
-
v-show 的陷阱:
- 坑 :在某些原生渲染(nvue)或特定小程序下,
v-show的表现可能不如预期(因为底层不支持display: none)。 - 避坑 :尽量使用
v-if控制显隐,除非该组件频繁切换且初始化极其耗时。
- 坑 :在某些原生渲染(nvue)或特定小程序下,
-
图片路径问题:
- 坑:背景图片如果是本地路径,在 App 端打包后经常找不到。
- 避坑 :小图片转 Base64,大图片必须放在
static目录下(绝对路径/static/xxx.png),或者直接使用网络图片(CDN)。
七、 最佳开发习惯建议
-
开发工具选择:
- 虽然可以用 VSCode,但强烈建议使用官方的 HBuilderX 。它的条件编译高亮、一键运行到微信开发者工具/真机、以及对
pages.json的智能提示,会为你节省大量配环境的时间。
- 虽然可以用 VSCode,但强烈建议使用官方的 HBuilderX 。它的条件编译高亮、一键运行到微信开发者工具/真机、以及对
-
多端同步预览:
- 不要在 H5(浏览器)里开发了整整一个月,最后才去跑微信小程序和 App。H5 是最宽容的平台。
- 正确姿势:开发时,至少同时打开浏览器(看 H5)和微信开发者工具(看小程序),确保样式和逻辑在双端表现一致。
-
拥抱 uniCloud(可选) :
- 如果你的项目没有后端,可以尝试官方的 uniCloud(Serverless 云开发),前端工程师可以直接用 JS 写云函数操作数据库,全栈开发体验极佳。
总结 : 把 uni-app 当作一个受限的 Vue 环境。收起操作 DOM 的野心,严格遵循数据驱动,善用条件编译处理平台差异,你就能在一周内成为跨端开发的高手。
以上内容仅代表个人理解,不喜勿碰,遗漏或者有误的欢迎评论区指出