uni-app 开发微信小程序实践案例:对接 uView、地图定位与微信能力

uni-app 开发微信小程序实践案例:对接 uView、地图定位与微信能力

本文以一个「门店/活动类」小程序常见需求为例,说明如何用 uni-app 编译到 微信小程序UI 统一对接 uView UI,并集成 微信地图与定位获取手机号 等能力,同时对比 微信原生框架 的取舍与 uni-app 注意点


1. UI 方案:uView 与 uni-app 版本对应

本案例的 UI 层以 uView 为准(通过 uni_modules 安装,组件前缀多为 u-)。

套件适用工程说明
uView UI 2.xuni-app + Vue 2生态成熟,文档与示例多
uView Plusuni-app + Vue 3Vue 3 项目选这一套,勿与 2.x 混装

安装与引入步骤以 uView 官方文档open in new window(或 uView Plus 站点)为准:一般包括 uni_modules 安装、在 main.js / main.tsapp.use(uView)、在 uni.scss 引入主题变量、在 pages.json 配置 easycom 实现 u- 组件按需加载。

名称辨析(避免搜错文档):口语里的「iView」多指 Web 后台的 View UI,与 uView 不是同一套库;小程序里对接 uni-app 组件库 请直接搜 uView / uView Plus


2. 案例背景(可落地的需求切片)

场景:线下活动报名页——需要展示地图选点、用户当前位置、表单里一键授权手机号(后端落库)。

技术栈:uni-app → 发行 mp-weixin;界面用 uView(如 u-buttonu-cellu-formu-modal 等);地图仍用原生 <map>(与 uView 不冲突);定位用 uni.getLocation;手机号用 u-buttonopen-type="getPhoneNumber"(需组件透传)或原生 button + 样式类同 uView。


3. 与「微信原生框架」对比:优点与代价

3.1 uni-app + uView 相对原生的优点

  1. 一套代码多端:同一业务可编译到微信、支付宝、H5、App 等(各端用条件编译处理差异)。
  2. Vue + uView 组件化:表单、列表、反馈类页面开发效率高,视觉与交互有统一规范。
  3. 工程化:npm、TypeScript、ESLint 等与前端工程对齐(视脚手架与版本而定)。

3.2 相对原生的不足或成本

  1. 调试链路更长:问题可能出在 Vue、编译器或微信基础库,排查比纯原生多一层。
  2. 包体积:uView 需 easycom 按需;避免全量引入导致主包过大。
  3. 新特性滞后:微信新 API 可能需 #ifdef MP-WEIXIN 直接调原生。
  4. 极致性能场景:复杂 canvas、游戏级动画等,原生或更可控。

简要结论:业务型、以表单/列表/地图为主的小程序,uni-app + uView 性价比高;强依赖最新微信底层能力或体积极致敏感时,要评估是否原生或混合。


4. 对接 uView:安装与使用要点

4.1 推荐步骤(概念清单)

  1. 用 HBuilderX 或 CLI 创建 uni-app 工程,先定 Vue2 或 Vue3,再选 uView 2.xuView Plus
  2. 通过 uni_modules 安装对应 uView 包。
  3. 按官方文档完成 main 入口uni.scss 变量pages.json → easycom
  4. 页面中直接使用 <u-button><u-input> 等;无需每个页面手动 import(easycom 生效时)。

4.2 使用注意

  • 按需加载:配置 easycom 规则,只打包实际用到的 u- 组件。
  • 微信开放能力按钮open-type(如 getPhoneNumberchooseAvatar)务必确认当前 uView 版本 是否将属性透传到原生 button。若文档未保证,手机号按钮建议用原生 <button> + 自定义 class,避免授权失败。
  • 主题:通过 uni.scss 覆盖 uView 变量,保持与品牌色一致。

4.3 代码佐证:入口、uni.scss 与 easycom(Vue2 + uView 2.x)

下面与 uView 官方文档一致,仅作结构佐证;Vue3 请改用 uView Plus 的安装方式。

main.js 中全局注册:

import Vue from "vue";
import App from "./App";
import uView from "uview-ui";

Vue.use(uView);

const app = new Vue({ ...App });
app.$mount();

uni.scss 引入主题变量(路径以你实际安装位置为准,uni_modules 方式可能不同):

@import "uview-ui/theme.scss";

pages.json 中配置 easycom,使 u-button 等无需逐页 import(规则以 uView 文档为准):

{
  "easycom": {
    "autoscan": true,
    "custom": {
      "^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
    }
  }
}

5. 微信地图、定位:uni-app 写法与注意点

5.1 能力说明

  • 地图展示:使用 <map>(编译到微信小程序为原生 map);外围可用 uView 的 u-cardu-gap 等排版。
  • 获取经纬度uni.getLocation(对应 wx.getLocation)。
  • 选点uni.chooseLocation(需权限与隐私说明)。

5.2 权限与隐私合规(必做)

  1. 在微信小程序后台配置「用户隐私保护指引」。
  2. manifest.json → 微信小程序 中配置 scope.userLocation 说明。
  3. 敏感接口按当前微信要求配置(如 requiredPrivateInfos,以微信与 uni-app 最新文档为准)。

5.3 坐标系

  • 一般使用 gcj02;与高德/百度等混用时注意坐标转换。

5.4 代码佐证:<map>uni.getLocation

模板里使用原生 <map>(编译到微信小程序即原生 map),与 uView 的 u-gapu-button 可同页混用:

<map
  class="map"
  :latitude="lat"
  :longitude="lng"
  :markers="markers"
  show-location
  @markertap="onMarkerTap"
/>

定位统一走 uni.getLocation,类型选 gcj02 与微信地图一致;成功后更新 lat/lngmarkers

uni.getLocation({
  type: "gcj02",
  isHighAccuracy: true,
  success: (res) => {
    this.lat = res.latitude;
    this.lng = res.longitude;
    this.markers = [
      {
        id: 1,
        latitude: res.latitude,
        longitude: res.longitude,
        title: "当前位置",
        width: 30,
        height: 30,
      },
    ];
  },
  fail: (err) => {
    uni.showToast({ title: "请开启定位权限", icon: "none" });
  },
});

可选:在业务里调用 uni.chooseLocation 让用户选点,返回的名称、地址、经纬度同样可用于更新 markers

5.5 代码佐证:权限与隐私(manifest / pages.json

微信小程序需在 manifest.jsonmp-weixin 中声明位置用途;敏感能力字段名随微信版本调整,以当时文档为准。示意:

{
  "mp-weixin": {
    "permission": {
      "scope.userLocation": {
        "desc": "你的位置信息将用于小程序地图展示"
      }
    },
    "requiredPrivateInfos": ["getLocation"]
  }
}

亦可在 pages.jsonmp-weixin 节点补充 permission(与工程习惯二选一或并存,以 uni-app 编译结果为准)。例如与 easycom、页面路由写在同一份 pages.json 时,可合并为:

{
  "pages": [
    {
      "path": "pages/demo/index",
      "style": { "navigationBarTitleText": "地图与授权示例" }
    }
  ],
  "easycom": {
    "autoscan": true,
    "custom": {
      "^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
    }
  },
  "mp-weixin": {
    "requiredPrivateInfos": ["getLocation"],
    "permission": {
      "scope.userLocation": {
        "desc": "用于在地图上展示你的位置"
      }
    }
  }
}

5.6 完整单页示例(uView + 地图 + 定位 + 手机号)

以下为一页 pages/demo/index.vue 的节选,可直接拷贝到工程(需已安装 uView 并配置 easycom;https://你的域名 换成合法业务域名):

<template>
  <view class="page">
    <u-gap height="20" />
    <map
      class="map"
      :latitude="lat"
      :longitude="lng"
      :markers="markers"
      show-location
      @markertap="onMarkerTap"
    />
    <u-gap height="24" />
    <u-button type="primary" @click="getLocation"
      >获取定位(uni.getLocation)</u-button
    >
    <u-gap height="24" />
    <u-button open-type="getPhoneNumber" @getphonenumber="onGetPhoneNumber">
      授权手机号
    </u-button>
    <u-gap height="16" />
    <u-text
      type="info"
      size="12"
      text="手机号 code 请发到自有后端解密,勿在前端拼 session_key。"
    />
  </view>
</template>

<script>
export default {
  data() {
    return {
      lat: 39.908823,
      lng: 116.39747,
      markers: [
        {
          id: 1,
          latitude: 39.908823,
          longitude: 116.39747,
          title: "示例点",
          width: 30,
          height: 30,
        },
      ],
    };
  },
  methods: {
    getLocation() {
      uni.getLocation({
        type: "gcj02",
        isHighAccuracy: true,
        success: (res) => {
          this.lat = res.latitude;
          this.lng = res.longitude;
          this.markers = [
            {
              id: 1,
              latitude: res.latitude,
              longitude: res.longitude,
              title: "当前位置",
              width: 30,
              height: 30,
            },
          ];
        },
        fail: () => {
          uni.showToast({ title: "请开启定位权限", icon: "none" });
        },
      });
    },
    onMarkerTap(e) {
      console.log("marker", e.detail);
    },
    onGetPhoneNumber(e) {
      // #ifdef MP-WEIXIN
      if (e.detail.errMsg === "getPhoneNumber:ok") {
        const code = e.detail.code;
        uni.request({
          url: "https://你的域名/api/wx/phone",
          method: "POST",
          data: { code },
        });
      } else {
        uni.showToast({ title: "用户未授权", icon: "none" });
      }
      // #endif
    },
  },
};
</script>

<style scoped>
.page {
  padding: 24rpx;
}
.map {
  width: 100%;
  height: 420rpx;
  border-radius: 12rpx;
  overflow: hidden;
}
</style>

6. 获取微信用户信息与手机号

6.1 用户信息(头像、昵称)

政策与接口常更新,以微信公众平台最新文档为准。可用 uView 表单组件承接用户输入的头像、昵称(使用微信提供的「头像昵称填写能力」时按官方组件要求)。

6.2 手机号(重点)

  1. 使用 open-type="getPhoneNumber",在 @getphonenumber 中取 code(新版)。
  2. 明文手机号只能由后端 用微信接口换取;前端禁止存放 AppSecret、session_key
  3. 需小程序资质与后台开通相关能力(如手机号快速验证)。

6.3 与 uView 的配合

  • 优先查阅 uView / uView Plus 文档中 u-buttonopenType 说明
  • 若透传不完整,用 原生 button + 与 uView 一致的 class 是最稳妥做法。

6.4 代码佐证:手机号按钮与回调(微信端)

模板(uView 的 u-button 需支持透传 open-type;否则换成原生 button):

<u-button open-type="getPhoneNumber" @getphonenumber="onGetPhoneNumber">
  授权手机号
</u-button>

回调里 只把 code 交给后端 换手机号(示例为前端请求占位,域名需加入小程序合法域名):

onGetPhoneNumber(e) {
  // #ifdef MP-WEIXIN
  if (e.detail.errMsg === 'getPhoneNumber:ok') {
    const code = e.detail.code
    uni.request({
      url: 'https://你的域名/api/wx/phone',
      method: 'POST',
      data: { code }
    })
  } else {
    uni.showToast({ title: '用户未授权', icon: 'none' })
  }
  // #endif
}

服务端使用微信提供的 手机号获取接口code 换明文(具体 URL、参数以微信开放平台当前文档为准),AppSecret、session_key 仅放服务端


7. uni-app 开发微信小程序的通用注意点

  1. 条件编译#ifdef MP-WEIXIN 隔离微信独有 API。
  2. 样式:注意安全区与 uView 默认间距。
  3. 网络:配置 request 合法域名
  4. 分包:页面多时拆分,控制主包体积(含 uView 按需)。
  5. Vue2 / Vue3 与 uView 大版本一一对应,勿混装。

7.1 代码佐证:条件编译

仅微信小程序打包的代码(例如 getPhoneNumber、部分 wx 能力)建议包在条件编译里,避免其它端报错:

onGetPhoneNumber(e) {
  // #ifdef MP-WEIXIN
  if (e.detail.errMsg === 'getPhoneNumber:ok') {
    const code = e.detail.code
    // ...
  }
  // #endif
}

模板侧若某组件仅小程序需要,可用 v-if 配合 // #ifdef 在构建期裁剪(具体写法以 uni-app 文档为准)。


8. 说明

main.jsuni.scsspages.jsonmanifest.json 与页面 .vue 的参考代码均已以上文 Markdown 代码块 形式给出;在本地用 HBuilderX 或 CLI 创建 uni-app 工程后,按路径新建文件并粘贴即可,无需再维护仓库内独立片段目录。


9. 小结

  • 本案例 UI 对接对象为 uView(Vue2 用 uView 2.x,Vue3 用 uView Plus),与 Web 端 iView / View UI 不是同一套。
  • 地图与定位 重点在权限、隐私合规与坐标系。
  • 手机号 必须前后端配合,前端只传 code

若将本文迁入博客,可在 frontmatter 中增加分类「技术实践 / 小程序」与日期。

Last Updated 4/9/2026, 6:16:02 AM