UniApp 与微信小程序详细对比
1. 开发环境
- 微信小程序:
- 主要使用微信开发者工具
- 提供模拟器、调试工具和性能监控
- 只能开发微信小程序
- UniApp:
- 主要使用 HBuilderX,但也支持 VS Code 等其他编辑器
- HBuilderX 提供可视化界面、代码提示、调试工具等
- 可以开发多平台应用,包括小程序、H5、App 等
2. 项目结构
-
微信小程序:
├── pages/ # 页面文件夹 ├── components/ # 自定义组件文件夹 ├── utils/ # 工具函数文件夹 ├── app.js # 全局 JS ├── app.json # 全局配置 ├── app.wxss # 全局样式 └── project.config.json # 项目配置文件
-
UniApp:
├── pages/ # 页面文件夹 ├── components/ # 自定义组件文件夹 ├── static/ # 静态资源文件夹 ├── store/ # Vuex 状态管理(可选) ├── App.vue # 应用配置,用来配置App全局样式以及监听应用生命周期 ├── main.js # Vue 初始化入口文件 ├── manifest.json # 配置应用名称、图标、权限等打包信息 └── pages.json # 配置页面路由、导航条、选项卡等页面类信息
3. 页面文件
- 微信小程序:
- .wxml:页面结构(类似 HTML)
- .wxss:页面样式(类似 CSS)
- .js:页面逻辑
- .json:页面配置
- UniApp:
- .vue 文件,包含三个部分:
<template>
:页面结构(支持小程序组件和 HTML 标签)<script>
:页面逻辑<style>
:页面样式(支持 CSS 预处理器,如 SCSS、Less)
- .vue 文件,包含三个部分:
4. 基础组件
微信小程序 | UniApp | 说明 |
---|---|---|
view | view | 视图容器,类似于 div |
text | text | 文本组件 |
image | image | 图片组件 |
button | button | 按钮组件 |
input | input | 输入框组件 |
textarea | textarea | 多行输入框组件 |
scroll-view | scroll-view | 可滚动视图区域 |
swiper | swiper | 滑块视图容器 |
navigator | navigator | 页面链接组件 |
progress | progress | 进度条组件 |
checkbox | checkbox | 多选框组件 |
radio | radio | 单选框组件 |
picker | picker | 底部弹起的滚动选择器 |
slider | slider | 滑动选择器 |
switch | switch | 开关选择器 |
form | form | 表单组件 |
注:UniApp 支持更多 HTML5 标准组件,在 App 端和 H5 端表现更接近标准 HTML。
5. 生命周期
微信小程序 | UniApp (Vue3 组合式 API) | 说明 |
---|---|---|
onLoad | onLoad | 页面加载时触发 |
onShow | onShow | 页面显示时触发 |
onReady | onReady | 页面初次渲染完成时触发 |
onHide | onHide | 页面隐藏时触发 |
onUnload | onUnload | 页面卸载时触发 |
onPullDownRefresh | onPullDownRefresh | 用户下拉刷新时触发 |
onReachBottom | onReachBottom | 页面上拉触底时触发 |
onShareAppMessage | onShareAppMessage | 用户点击右上角分享时触发 |
onPageScroll | onPageScroll | 页面滚动时触发 |
onTabItemTap | onTabItemTap | 点击 tab 时触发 |
onResize | onResize | 页面尺寸变化时触发 |
注:
- UniApp 在 Vue3 组合式 API 中,这些钩子需要单独引入使用。
- UniApp 还提供了额外的应用生命周期,如 onLaunch、onShow、onHide 等。
6. 数据绑定与更新
-
微信小程序:
javascriptPage({ data: { message: 'Hello', list: [1, 2, 3] }, changeMessage() { this.setData({ message: 'Hi', 'list[0]': 4 // 修改数组元素 }) } })
html<view>{{message}}</view> <view wx:for="{{list}}" wx:key="*this">{{item}}</view>
-
UniApp (Vue3 组合式 API):
javascriptimport { ref, reactive } from 'vue' export default { setup() { const message = ref('Hello') const list = reactive([1, 2, 3]) function changeMessage() { message.value = 'Hi' list[0] = 4 // 直接修改响应式数组 } return { message, list, changeMessage } } }
html<view>{{message}}</view> <view v-for="item in list" :key="item">{{item}}</view>
7. 条件渲染
-
微信小程序:
html<view wx:if="{{condition}}">True</view> <view wx:elif="{{condition2}}">Condition2</view> <view wx:else>False</view>
-
UniApp:
html<view v-if="condition">True</view> <view v-else-if="condition2">Condition2</view> <view v-else>False</view>
8. 列表渲染
-
微信小程序:
html<view wx:for="{{items}}" wx:key="id"> {{index}}: {{item.name}} </view>
-
UniApp:
html<view v-for="(item, index) in items" :key="item.id"> {{index}}: {{item.name}} </view>
9. 事件处理
-
微信小程序:
html<button bindtap="handleClick" data-id="{{item.id}}">点击</button>
javascriptPage({ handleClick(event) { const id = event.currentTarget.dataset.id console.log('Clicked item:', id) } })
-
UniApp:
html<button @click="handleClick(item.id)">点击</button>
javascriptexport default { methods: { handleClick(id) { console.log('Clicked item:', id) } } }
10. 路由导航
-
微信小程序:
javascript// 页面跳转 wx.navigateTo({ url: '/pages/about/about?id=1' }) // 页面重定向 wx.redirectTo({ url: '/pages/login/login' }) // 页面返回 wx.navigateBack({ delta: 1 }) // Tab 切换 wx.switchTab({ url: '/pages/home/home' })
-
UniApp:
javascript// 页面跳转 uni.navigateTo({ url: '/pages/about/about?id=1' }) // 页面重定向 uni.redirectTo({ url: '/pages/login/login' }) // 页面返回 uni.navigateBack({ delta: 1 }) // Tab 切换 uni.switchTab({ url: '/pages/home/home' })
11. 网络请求
-
微信小程序:
javascriptwx.request({ url: 'https://api.example.com/data', method: 'GET', data: { id: 1 }, header: { 'content-type': 'application/json' }, success(res) { console.log(res.data) }, fail(err) { console.error(err) } })
-
UniApp:
javascriptuni.request({ url: 'https://api.example.com/data', method: 'GET', data: { id: 1 }, header: { 'content-type': 'application/json' }, success(res) { console.log(res.data) }, fail(err) { console.error(err) } })
注:UniApp 还支持使用
async/await
语法:javascripttry { const res = await uni.request({ url: 'https://api.example.com/data', method: 'GET', data: { id: 1 } }) console.log(res.data) } catch (err) { console.error(err) }
12. 存储
-
微信小程序:
javascript// 设置存储 wx.setStorageSync('key', 'value') // 获取存储 const value = wx.getStorageSync('key') // 移除存储 wx.removeStorageSync('key') // 清除所有存储 wx.clearStorageSync()
-
UniApp:
javascript// 设置存储 uni.setStorageSync('key', 'value') // 获取存储 const value = uni.getStorageSync('key') // 移除存储 uni.removeStorageSync('key') // 清除所有存储 uni.clearStorageSync()
13. 组件创建和使用
-
微信小程序:
创建组件(my-component.js):
javascriptComponent({ properties: { myProperty: { type: String, value: '' } }, data: { innerValue: '' }, methods: { myMethod() { // 方法实现 } } })
使用组件(在页面的 json 文件中):
json{ "usingComponents": { "my-component": "/components/my-component/my-component" } }
在 wxml 中:
html<my-component my-property="value"></my-component>
-
UniApp:
创建组件(MyComponent.vue):
vue<template> <view>{{myProperty}}</view> </template> <script> export default { name: 'MyComponent', props: { myProperty: { type: String, default: '' } }, data() { return { innerValue: '' } }, methods: { myMethod() { // 方法实现 } } } </script>
使用组件(在父组件中):
vue<template> <my-component :my-property="value"></my-component> </template> <script> import MyComponent from '@/components/MyComponent.vue' export default { components: { MyComponent } } </script>
14. 全局配置
-
微信小程序(app.json):
json{ "pages": [ "pages/index/index", "pages/logs/logs" ], "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#fff", "navigationBarTitleText": "WeChat", "navigationBarTextStyle": "black" }, "tabBar": { "list": [ { "pagePath": "pages/index/index", "text": "首页" }, { "pagePath": "pages/logs/logs", "text": "日志" } ] } }
-
UniApp:
pages.json:json{ "pages": [ { "path": "pages/index/index", "style": { "navigationBarTitleText": "首页" } }, { "path": "pages/logs/logs", "style": { "navigationBarTitleText": "日志" } } ], "globalStyle": { "navigationBarTextStyle": "black", "navigationBarTitleText": "UniApp", "navigationBarBackgroundColor": "#F8F8F8", "backgroundColor": "#F8F8F8" }, "tabBar": { "color": "#7A7E83", "selectedColor": "#3cc51f", "borderStyle": "black", "backgroundColor": "#