Skip to content
alex's blog
Go back

UniApp 入门指南 - 跨平台开发从零开始

编辑页面

UniApp 是 DCloud 推出的跨平台开发框架,使用 Vue.js 语法,可以一套代码编译到 iOS、Android、H5、以及各种小程序平台。本文将带你从零开始学习 UniApp。

什么是 UniApp?

UniApp 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到 iOS、Android、H5、以及各种小程序(微信/支付宝/百度/头条/QQ/快手/钉钉/淘宝)、快应用等多个平台。

核心优势

  1. 一套代码,多端运行:编写一次,发布到多个平台
  2. Vue.js 语法:学习成本低,上手快
  3. 丰富的组件库:内置大量 UI 组件
  4. 性能优秀:接近原生应用的性能
  5. 生态完善:插件市场丰富

环境搭建

1. 安装 HBuilderX

HBuilderX 是 DCloud 官方推荐的开发工具:

  1. 访问 HBuilderX 官网
  2. 下载并安装 HBuilderX
  3. 安装 uni-app 插件

2. 创建项目

在 HBuilderX 中:

  1. 文件 → 新建 → 项目
  2. 选择 uni-app
  3. 选择模板(推荐使用默认模板)
  4. 填写项目名称和路径

3. 使用 CLI 创建项目

# 全局安装 vue-cli
npm install -g @vue/cli

# 创建 uni-app 项目
vue create -p dcloudio/uni-preset-vue my-project

# 进入项目目录
cd my-project

# 运行到 H5
npm run dev:h5

# 运行到微信小程序
npm run dev:mp-weixin

项目结构

my-project/
├── pages/              # 页面目录
│   ├── index/
│   │   └── index.vue
│   └── about/
│       └── about.vue
├── components/         # 组件目录
├── static/             # 静态资源
├── App.vue            # 应用入口
├── main.js            # 入口文件
├── manifest.json      # 应用配置
└── pages.json        # 页面路由配置

基础语法

1. 页面结构

<template>
  <view class="container">
    <text>{{ message }}</text>
    <button @click="handleClick">点击我</button>
  </view>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello UniApp!'
    }
  },
  methods: {
    handleClick() {
      uni.showToast({
        title: '点击成功',
        icon: 'success'
      })
    }
  }
}
</script>

<style>
.container {
  padding: 20px;
}
</style>

2. 生命周期

<script>
export default {
  onLoad(options) {
    // 页面加载时触发
    console.log('页面加载', options)
  },
  onShow() {
    // 页面显示时触发
    console.log('页面显示')
  },
  onReady() {
    // 页面初次渲染完成
    console.log('页面渲染完成')
  },
  onHide() {
    // 页面隐藏时触发
    console.log('页面隐藏')
  },
  onUnload() {
    // 页面卸载时触发
    console.log('页面卸载')
  }
}
</script>

3. 路由导航

// 保留当前页面,跳转到应用内的某个页面
uni.navigateTo({
  url: '/pages/detail/detail?id=123'
})

// 关闭当前页面,跳转到应用内的某个页面
uni.redirectTo({
  url: '/pages/index/index'
})

// 跳转到 tabBar 页面
uni.switchTab({
  url: '/pages/index/index'
})

// 返回上一页面
uni.navigateBack({
  delta: 1 // 返回的页面数
})

常用组件

1. view 容器组件

<template>
  <view class="container">
    <view class="box">内容区域</view>
  </view>
</template>

2. text 文本组件

<template>
  <text>普通文本</text>
  <text class="highlight">高亮文本</text>
</template>

3. image 图片组件

<template>
  <image 
    src="/static/logo.png" 
    mode="aspectFit"
    @error="handleError"
  />
</template>

4. button 按钮组件

<template>
  <button type="primary" @click="handleClick">
    主要按钮
  </button>
  <button type="default">默认按钮</button>
  <button type="warn">警告按钮</button>
</template>

5. input 输入框

<template>
  <input 
    v-model="inputValue"
    placeholder="请输入内容"
    @input="handleInput"
  />
</template>

<script>
export default {
  data() {
    return {
      inputValue: ''
    }
  },
  methods: {
    handleInput(e) {
      console.log('输入值:', e.detail.value)
    }
  }
}
</script>

条件渲染和列表渲染

条件渲染

<template>
  <view>
    <view v-if="show">显示内容</view>
    <view v-else>隐藏内容</view>
    
    <view v-show="visible">v-show 控制</view>
  </view>
</template>

列表渲染

<template>
  <view>
    <view v-for="(item, index) in list" :key="index">
      {{ item.name }}
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      list: [
        { name: '项目1' },
        { name: '项目2' },
        { name: '项目3' }
      ]
    }
  }
}
</script>

API 使用

1. 网络请求

// 使用 uni.request
uni.request({
  url: 'https://api.example.com/data',
  method: 'GET',
  data: {
    id: 123
  },
  success: (res) => {
    console.log('请求成功', res.data)
  },
  fail: (err) => {
    console.error('请求失败', err)
  }
})

// 封装请求方法
const request = (url, method = 'GET', data = {}) => {
  return new Promise((resolve, reject) => {
    uni.request({
      url,
      method,
      data,
      success: (res) => {
        if (res.statusCode === 200) {
          resolve(res.data)
        } else {
          reject(res)
        }
      },
      fail: reject
    })
  })
}

// 使用
async function fetchData() {
  try {
    const data = await request('https://api.example.com/data')
    console.log(data)
  } catch (error) {
    console.error(error)
  }
}

2. 数据存储

// 同步存储
uni.setStorageSync('key', 'value')
const value = uni.getStorageSync('key')

// 异步存储
uni.setStorage({
  key: 'key',
  data: 'value',
  success: () => {
    console.log('存储成功')
  }
})

uni.getStorage({
  key: 'key',
  success: (res) => {
    console.log('获取成功', res.data)
  }
})

3. 页面交互

// 显示提示
uni.showToast({
  title: '操作成功',
  icon: 'success',
  duration: 2000
})

// 显示加载
uni.showLoading({
  title: '加载中...'
})

// 隐藏加载
uni.hideLoading()

// 显示模态框
uni.showModal({
  title: '提示',
  content: '确定要删除吗?',
  success: (res) => {
    if (res.confirm) {
      console.log('用户点击确定')
    }
  }
})

样式处理

1. 单位使用

<style>
.container {
  width: 750rpx;  /* rpx 是响应式单位,750rpx = 屏幕宽度 */
  height: 100vh;  /* 视口高度 */
  padding: 20rpx;
}
</style>

2. 条件编译

<template>
  <!-- #ifdef H5 -->
  <view>H5 平台显示</view>
  <!-- #endif -->
  
  <!-- #ifdef MP-WEIXIN -->
  <view>微信小程序显示</view>
  <!-- #endif -->
  
  <!-- #ifdef APP-PLUS -->
  <view>App 平台显示</view>
  <!-- #endif -->
</template>

<script>
// #ifdef H5
console.log('H5 平台')
// #endif

// #ifdef MP-WEIXIN
console.log('微信小程序平台')
// #endif
</script>

配置说明

pages.json

{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页"
      }
    }
  ],
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "UniApp",
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8"
  },
  "tabBar": {
    "color": "#7A7E83",
    "selectedColor": "#3cc51f",
    "borderStyle": "black",
    "backgroundColor": "#ffffff",
    "list": [
      {
        "pagePath": "pages/index/index",
        "iconPath": "static/tab-home.png",
        "selectedIconPath": "static/tab-home-current.png",
        "text": "首页"
      }
    ]
  }
}

manifest.json

{
  "name": "my-app",
  "appid": "",
  "description": "",
  "versionName": "1.0.0",
  "versionCode": "100",
  "transformPx": false,
  "app-plus": {
    "usingComponents": true
  },
  "h5": {
    "router": {
      "mode": "hash"
    }
  },
  "mp-weixin": {
    "appid": "",
    "setting": {
      "urlCheck": false
    }
  }
}

实战示例

示例 1: 列表页面

<template>
  <view class="container">
    <view 
      v-for="(item, index) in list" 
      :key="index"
      class="list-item"
      @click="goToDetail(item)"
    >
      <image :src="item.image" class="item-image" />
      <view class="item-content">
        <text class="item-title">{{ item.title }}</text>
        <text class="item-desc">{{ item.desc }}</text>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      list: []
    }
  },
  onLoad() {
    this.fetchList()
  },
  methods: {
    async fetchList() {
      try {
        const res = await uni.request({
          url: 'https://api.example.com/list'
        })
        this.list = res.data
      } catch (error) {
        uni.showToast({
          title: '加载失败',
          icon: 'none'
        })
      }
    },
    goToDetail(item) {
      uni.navigateTo({
        url: `/pages/detail/detail?id=${item.id}`
      })
    }
  }
}
</script>

<style>
.container {
  padding: 20rpx;
}

.list-item {
  display: flex;
  padding: 20rpx;
  margin-bottom: 20rpx;
  background: #fff;
  border-radius: 10rpx;
}

.item-image {
  width: 120rpx;
  height: 120rpx;
  border-radius: 10rpx;
}

.item-content {
  flex: 1;
  margin-left: 20rpx;
}

.item-title {
  font-size: 32rpx;
  font-weight: bold;
}

.item-desc {
  font-size: 28rpx;
  color: #999;
  margin-top: 10rpx;
}
</style>

调试技巧

  1. H5 调试:使用浏览器开发者工具
  2. 小程序调试:使用对应平台的开发者工具
  3. App 调试:使用 HBuilderX 的真机运行功能
  4. 控制台输出:使用 console.log 查看日志

常见问题

1. 样式不生效?

2. 页面跳转失败?

3. 网络请求失败?

总结

UniApp 是一个强大的跨平台开发框架,通过本文的学习,你应该能够:

  1. 搭建 UniApp 开发环境
  2. 创建和配置项目
  3. 使用基础组件和 API
  4. 实现页面导航和数据交互
  5. 进行条件编译和样式处理

接下来可以深入学习:

开始你的 UniApp 跨平台开发之旅吧!


UniApp 让跨平台开发变得简单高效,一套代码多端运行,大大提升了开发效率。


编辑页面
Share this post on:

Previous Post
UniApp 跨平台开发最佳实践
Next Post
Flutter Widget 生命周期与构建优化