UniApp跨端开发完全指南:一套代码多端发布实战教程

2025-09-06 0 902

掌握一套代码发布到iOS、Android、Web及多种小程序的终极解决方案

什么是UniApp?

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

UniApp由DCloud公司开发,基于Vue.js语法规范,使用HBuilderX作为官方IDE,提供了丰富的组件和API,大大提高了跨端开发的效率。它解决了多端开发中重复编写代码的痛点,让开发者可以专注于业务逻辑的实现。

UniApp的主要优势

  • 跨平台能力 – 一套代码可编译到14个平台
  • 性能接近原生 – 使用weex原生渲染引擎,提升用户体验
  • 丰富的生态系统 – 插件市场提供数千款插件
  • 学习成本低 – 基于Vue.js语法,前端开发者快速上手
  • 开发效率高 – HBuilderX提供强大的开发调试功能

开发环境搭建

1. 安装HBuilderX

HBuilderX是UniApp官方推荐的IDE,提供了丰富的开发功能和调试工具:

  1. 访问HBuilderX官网下载对应版本
  2. 安装并启动HBuilderX
  3. 安装必要的插件(如vue语法提示、uniapp语法提示等)

2. 创建第一个UniApp项目

在HBuilderX中创建新项目:

  1. 点击菜单”文件” -> “新建” -> “项目”
  2. 选择”uni-app”项目类型
  3. 选择默认模板或官方示例模板
  4. 输入项目名称和存储路径
  5. 点击创建完成项目初始化

3. 安装开发依赖(可选)

如需使用npm管理依赖:

# 在项目根目录执行
npm init -y
npm install @dcloudio/uni-ui  # 安装官方UI组件库

4. 运行项目

在HBuilderX中:

  • 选择运行到浏览器
  • 选择运行到手机或模拟器
  • 选择运行到小程序开发者工具

UniApp基础概念

项目结构

一个典型的UniApp项目包含以下目录结构:

uni-app-project/
  ├── pages/                 // 页面目录
  │   └── index/
  │       ├── index.vue      // 页面组件
  │       └── index.json     // 页面配置
  ├── static/               // 静态资源目录
  ├── components/           // 自定义组件目录
  ├── uni_modules/          // uni模块目录
  ├── App.vue              // 应用入口组件
  ├── main.js              // 应用入口js
  ├── manifest.json        // 应用配置文件
  └── pages.json           // 页面配置文件

页面生命周期

UniApp页面支持Vue组件生命周期,同时增加了应用级生命周期:

export default {
  // 页面生命周期
  onLoad(options) {
    // 页面加载时触发
  },
  onShow() {
    // 页面显示时触发
  },
  onReady() {
    // 页面初次渲染完成时触发
  },
  onHide() {
    // 页面隐藏时触发
  },
  onUnload() {
    // 页面卸载时触发
  },
  // Vue生命周期
  created() {
    // Vue实例创建后调用
  },
  mounted() {
    // Vue实例挂载后调用
  }
}

路由系统

UniApp使用小程序风格的路由系统:

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

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

// 跳转到tabBar页面,并关闭其他所有非tabBar页面
uni.switchTab({
  url: '/pages/category/category'
})

// 关闭所有页面,打开到应用内的某个页面
uni.reLaunch({
  url: '/pages/login/login'
})

UniApp核心组件

UniApp提供了一系列跨端兼容的组件,这些组件在不同平台上会有相应的原生组件实现:

视图容器组件

<!-- view组件 - 视图容器 -->
<view class="container">
  <text>这是一个文本内容</text>
</view>

<!-- scroll-view组件 - 可滚动视图区域 -->
<scroll-view scroll-y="true" style="height: 300px;">
  <view v-for="item in list" :key="item.id">
    {{ item.name }}
  </view>
</scroll-view>

<!-- swiper组件 - 滑块视图容器 -->
<swiper :indicator-dots="true" :autoplay="true" :interval="3000">
  <swiper-item v-for="(item, index) in banners" :key="index">
    <image :src="item.image" mode="aspectFill"></image>
  </swiper-item>
</swiper>

基础内容组件

<!-- text组件 - 文本组件 -->
<text selectable="true" space="ensp">这段文本可以选择复制</text>

<!-- rich-text组件 - 富文本组件 -->
<rich-text :nodes="htmlContent"></rich-text>

<!-- progress组件 - 进度条组件 -->
<progress :percent="70" show-info stroke-width="5"></progress>

表单组件

<!-- input组件 - 输入框 -->
<input v-model="username" placeholder="请输入用户名" />

<!-- checkbox组件 - 多项选择器 -->
<checkbox-group @change="checkboxChange">
  <label v-for="item in items" :key="item.value">
    <checkbox :value="item.value" :checked="item.checked" />
    {{ item.name }}
  </label>
</checkbox-group>

<!-- picker组件 - 选择器 -->
<picker mode="date" :value="date" @change="bindDateChange">
  <view class="picker">
    当前选择: {{date}}
  </view>
</picker>

UniApp常用API

UniApp提供了丰富的API,用于调用设备功能和平台特性:

网络请求

// 发起GET请求
uni.request({
  url: 'https://api.example.com/data',
  method: 'GET',
  data: {
    page: 1,
    limit: 10
  },
  success: (res) => {
    console.log('请求成功:', res.data);
  },
  fail: (err) => {
    console.error('请求失败:', err);
  }
});

// 上传文件
uni.uploadFile({
  url: 'https://api.example.com/upload',
  filePath: tempFilePaths[0],
  name: 'file',
  success: (uploadRes) => {
    console.log('上传成功:', uploadRes.data);
  }
});

数据缓存

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

// 同步存储数据
uni.setStorageSync('token', 'abcdef123456');

// 获取数据
const token = uni.getStorageSync('token');

// 移除数据
uni.removeStorage({
  key: 'userInfo'
});

设备相关API

// 获取系统信息
uni.getSystemInfo({
  success: (res) => {
    console.log('手机型号:', res.model);
    console.log('系统版本:', res.system);
  }
});

// 拨打电话
uni.makePhoneCall({
  phoneNumber: '10086'
});

// 获取地理位置
uni.getLocation({
  type: 'wgs84',
  success: (res) => {
    console.log('当前位置:', res.latitude, res.longitude);
  }
});

实战项目:多端商品展示应用

下面我们创建一个简单的商品展示应用,演示UniApp的开发流程:

项目结构

shop-demo/
  ├── pages/
  │   ├── index/
  │   │   ├── index.vue      // 首页
  │   │   └── index.json     // 首页配置
  │   ├── category/
  │   │   ├── category.vue   // 分类页
  │   │   └── category.json
  │   ├── cart/
  │   │   ├── cart.vue       // 购物车页
  │   │   └── cart.json
  │   ├── product/
  │   │   ├── list.vue       // 商品列表页
  │   │   ├── detail.vue     // 商品详情页
  │   │   └── detail.json
  │   └── user/
  │       ├── user.vue       // 用户中心页
  │       └── user.json
  ├── components/
  │   ├── product-card.vue   // 商品卡片组件
  │   └── tab-bar.vue        // 自定义标签栏
  ├── static/
  │   ├── images/
  │   └── icons/
  ├── store/
  │   └── index.js           // Vuex状态管理
  ├── App.vue
  ├── main.js
  ├── manifest.json
  └── pages.json

首页实现 (index.vue)

<template>
  <view class="page-container">
    <!-- 搜索栏 -->
    <view class="search-bar">
      <uni-search-bar placeholder="搜索商品" @confirm="onSearch"></uni-search-bar>
    </view>
    
    <!-- 轮播图 -->
    <swiper class="swiper" :indicator-dots="true" :autoplay="true" :interval="3000">
      <swiper-item v-for="(banner, index) in banners" :key="index">
        <image :src="banner.image" mode="aspectFill" class="swiper-image" @click="onBannerClick(banner)"></image>
      </swiper-item>
    </swiper>
    
    <!-- 分类导航 -->
    <view class="category-nav">
      <view v-for="category in categories" :key="category.id" class="nav-item" @click="onCategoryClick(category)">
        <image :src="category.icon" mode="aspectFit" class="nav-icon"></image>
        <text class="nav-text">{{ category.name }}</text>
      </view>
    </view>
    
    <!-- 商品列表 -->
    <view class="section-title">热门推荐</view>
    <view class="product-list">
      <product-card 
        v-for="product in products" 
        :key="product.id" 
        :product="product"
        @click="onProductClick(product)">
      </product-card>
    </view>
  </view>
</template>

<script>
import { mapState, mapActions } from 'vuex';
import ProductCard from '@/components/product-card.vue';

export default {
  components: {
    ProductCard
  },
  data() {
    return {
      banners: [],
      categories: [],
      products: []
    };
  },
  computed: {
    ...mapState(['userInfo'])
  },
  onLoad() {
    this.loadHomeData();
  },
  methods: {
    ...mapActions(['addToCart']),
    
    async loadHomeData() {
      // 模拟API请求
      try {
        const [bannerRes, categoryRes, productRes] = await Promise.all([
          uni.request({ url: '/api/banners' }),
          uni.request({ url: '/api/categories' }),
          uni.request({ url: '/api/products/hot' })
        ]);
        
        this.banners = bannerRes.data;
        this.categories = categoryRes.data;
        this.products = productRes.data;
      } catch (error) {
        uni.showToast({
          title: '数据加载失败',
          icon: 'none'
        });
      }
    },
    
    onSearch(keyword) {
      uni.navigateTo({
        url: `/pages/product/list?keyword=${keyword}`
      });
    },
    
    onBannerClick(banner) {
      if (banner.link) {
        uni.navigateTo({
          url: banner.link
        });
      }
    },
    
    onCategoryClick(category) {
      uni.navigateTo({
        url: `/pages/product/list?categoryId=${category.id}`
      });
    },
    
    onProductClick(product) {
      uni.navigateTo({
        url: `/pages/product/detail?id=${product.id}`
      });
    }
  }
};
</script>

商品卡片组件 (product-card.vue)

<template>
  <view class="product-card" @click="$emit('click', product)">
    <image :src="product.image" mode="aspectFill" class="product-image"></image>
    <view class="product-info">
      <text class="product-name">{{ product.name }}</text>
      <text class="product-desc">{{ product.description }}</text>
      <view class="product-bottom">
        <text class="product-price">¥{{ product.price }}</text>
        <view class="action-buttons">
          <uni-icons 
            type="plus" 
            size="20" 
            color="#ff6700" 
            @click.stop="onAddToCart">
          </uni-icons>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  props: {
    product: {
      type: Object,
      required: true
    }
  },
  methods: {
    onAddToCart() {
      this.$emit('add-to-cart', this.product);
      uni.showToast({
        title: '已加入购物车',
        icon: 'success'
      });
    }
  }
};
</script>

多端发布指南

发布到微信小程序

  1. 在微信公众平台注册小程序账号并获取AppID
  2. 在HBuilderX中打开manifest.json文件
  3. 配置微信小程序AppID
  4. 点击”发行” -> “小程序-微信”
  5. 等待编译完成,自动打开微信开发者工具
  6. 在微信开发者工具中上传代码并提交审核

发布到App

  1. 配置manifest.json中的App设置
  2. 点击”发行” -> “原生App-云打包”
  3. 选择需要打包的平台(iOS/Android)
  4. 配置证书(Android使用自有证书,iOS需提供证书文件)
  5. 等待云端打包完成,下载安装包
  6. 提交到各应用市场(App Store、各大安卓市场)

发布到H5

  1. 配置manifest.json中的H5设置
  2. 点击”发行” -> “网站-H5手机版”
  3. 设置网站标题和域名
  4. 等待编译完成,将生成的目录部署到服务器
  5. 配置服务器路由 history 模式(如需)

条件编译

UniApp提供了条件编译语法,处理不同平台的差异:

// #ifdef H5
console.log('仅在H5平台编译此代码');
// #endif

// #ifdef MP-WEIXIN
console.log('仅在微信小程序平台编译此代码');
// #endif

// #ifdef APP-PLUS
console.log('仅在App平台编译此代码');
// #endif

<!-- 条件编译示例 -->
<view>
  <!-- 在H5和微信小程序中显示 -->
  <button>通用按钮</button>
  <!-- #ifdef H5 -->
  <a href="/about" rel="external nofollow" >关于我们</a>
  <!-- #endif -->
  <!-- #ifdef MP-WEIXIN -->
  <button open-type="contact">联系我们</button>
  <!-- #endif -->
</view>

UniApp跨端开发完全指南:一套代码多端发布实战教程
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 uniapp UniApp跨端开发完全指南:一套代码多端发布实战教程 https://www.taomawang.com/web/uniapp/1033.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务