uni-app小程序前端开发笔记(更新中)

创建uni-app 项目

uni-app 支持两种方式创建项目:

  1. 通过HBuilderX 创建 2. 通过命令行创建

具体操作

pages.json 和 tabBar 案例

静态资源(static)尽量不超过2MB,不方便打包

pages.json
  • pages 页面路由及窗口表现
  • globalstyle 默认窗口表现
  • tabBar 至少两个才显示
TypeScript 复制代码
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
		{
			"path": "pages/index/index",
			"style": {
				"navigationBarTitleText": "uni-app"
			}
		},

		{
			"path": "pages/my/my",
			"style": {
				"navigationBarTitleText": "my"
			}
		}
	],
	"globalStyle": {
		"navigationBarTextStyle": "white",
		"navigationBarTitleText": "uni-app",
		"navigationBarBackgroundColor": "#00ced1",
		"backgroundColor": "#F8F8F8"
	},
	"tabBar": {
		"selectedColor": "#00ced1",
		"list": [
			{
				"pagePath": "pages/index/index",
				"text": "首页",
				"iconPath": "/static/tabs/home_default.png",
				"selectedIconPath": "/static/tabs/home_selected.png"
			},
			{
				"pagePath": "pages/my/my",
				"text": "我的",
				"iconPath": "/static/tabs/user_default.png",
				"selectedIconPath": "/static/tabs/user_selected.png"
				
			}

uni-app 和 原生小程序开发区别

每个页面是一个.vue 文件,数据绑定及事件处理同Vue.js 规范:

  1. 属性绑定 src="{{ url }}" 升级成 :src="url"

  2. 事件绑定 bindtap="eventName" 升级成 @tap="eventName",支持()传参

  3. 支持Vue 常用指令 v-for、v-if、v-show、v-model 等

调用接口能力,建议前缀wx 替换为uni,养成好习惯,这样支持多端开发。

一、项目模板拉取与基础架构搭建

1. 拉取小兔鲜儿项目模板

TypeScript 复制代码
# 克隆项目模板代码
git clone http://git.itcast.cn/heimaqianduan/erabbit-uni-app-vue3-ts.git heima-shop

# 进入项目目录
cd heima-shop

# 安装依赖(需提前安装pnpm)
pnpm install

# 编译为微信小程序代码
pnpm dev:mp-weixin
关键配置
  • manifest.json中添加微信小程序appid(登录微信公众平台获取)
  • 编译完成后,打开微信开发者工具,导入unpackage/dist/dev/mp-weixin目录即可预览

2. 集成 uni-ui 组件库(自动引入)

安装依赖
TypeScript 复制代码
# 安装uni-ui组件库
pnpm i @dcloudio/uni-ui

# 安装组件类型声明(TS项目必备)
pnpm i -D @uni-helper/uni-ui-types
配置自动引入(pages.json)
TypeScript 复制代码
{
  "easycom": {
    "autoscan": true,
    "custom": {
      // 匹配uni-ui组件,无需手动import
      "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
    }
  },
  "pages": [/* 原有页面配置 */]
}
配置 TS 类型(tsconfig.json)
TypeScript 复制代码
{
  "compilerOptions": {
    "types": [
      "@dcloudio/types",
      "@types/wechat-miniprogram",
      "@uni-helper/uni-app-types",
      "@uni-helper/uni-ui-types" // 新增uni-ui类型声明
    ]
  }
}

3. Pinia 状态持久化

核心差异
  • 小程序不支持浏览器的localStorage,需使用uni.setStorageSync()/uni.getStorageSync()替代
  • 通过 Pinia 的persist配置自定义存储逻辑,实现多端兼容
代码示例(stores/modules/member.ts)
TypeScript 复制代码
import { defineStore } from 'pinia'

// 用户信息状态管理
export const useMemberStore = defineStore('member', {
  state: () => ({
    profile: null // 存储用户登录信息
  }),
  persist: {
    // 自定义持久化存储方式
    storage: {
      // 存储数据:使用uni-app多端兼容API
      setItem(key: string, value: string) {
        uni.setStorageSync(key, value)
      },
      // 读取数据:对应读取API
      getItem(key: string) {
        return uni.getStorageSync(key)
      }
    }
  },
  actions: {
    // 清空用户信息(退出登录时调用)
    clearProfile() {
      this.profile = null
    }
  }
})

二、核心工具封装:uni.request 请求封装

1. 封装思路

  • 统一基础地址、超时时间、请求头
  • 拦截请求添加身份标识(source-client)和 Token
  • 统一响应处理(状态码判断、错误提示、401 跳转登录)
  • 支持 TypeScript 类型推导,返回结构化数据

2. 完整封装代码(utils/http.ts)

TypeScript 复制代码
import { useMemberStore } from '@/stores/modules/member'

// 定义响应数据结构
interface Data<T> {
  code: string
  msg: string
  result: T
}

// 基础地址(首选+备用)
const baseURL = 'https://pcapi-xiaotuxian-front-devtest.itheima.net'
// const baseURL = 'https://pcapi-xiaotuxian-front.itheima.net' // 备用地址

// 请求拦截器配置
const httpInterceptor = {
  // 拦截前触发
  invoke(options: UniApp.RequestOptions) {
    // 1. 拼接基础地址(非http开头需拼接)
    if (!options.url.startsWith('http')) {
      options.url = baseURL + options.url
    }
    // 2. 设置超时时间(10秒)
    options.timeout = 10000
    // 3. 添加小程序端请求头标识
    options.header = {
      ...options.header,
      'source-client': 'miniapp' // 服务端识别客户端类型
    }
    // 4. 添加Token(登录后获取)
    const memberStore = useMemberStore()
    const token = memberStore.profile?.token
    if (token) {
      options.header.Authorization = token
    }
  }
}

// 注册请求拦截器(拦截request和uploadFile)
uni.addInterceptor('request', httpInterceptor)
uni.addInterceptor('uploadFile', httpInterceptor)

// 封装Promise请求函数
export const http = <T>(options: UniApp.RequestOptions) => {
  return new Promise<Data<T>>((resolve, reject) => {
    uni.request({
      ...options,
      // 响应成功处理
      success(res) {
        // 2xx状态码:获取数据成功
        if (res.statusCode >= 200 && res.statusCode < 300) {
          resolve(res.data as Data<T>)
        }
        // 401状态码:Token失效,跳转登录页
        else if (res.statusCode === 401) {
          const memberStore = useMemberStore()
          memberStore.clearProfile() // 清空用户信息
          uni.navigateTo({ url: '/pages/login/login' }) // 跳转登录
          reject(res)
        }
        // 其他状态码:通用错误提示
        else {
          uni.showToast({
            icon: 'none',
            title: (res.data as Data<T>).msg || '数据获取失败'
          })
          reject(res)
        }
      },
      // 响应失败处理(网络错误)
      fail(err) {
        uni.showToast({
          icon: 'none',
          title: '网络错误,换个网络试试'
        })
        reject(err)
      }
    })
  })
}

3. 使用示例

TypeScript 复制代码
// 定义数据类型(TS类型推导)
interface BannerItem {
  id: number
  imageUrl: string
  link: string
}

// 调用请求函数
const getBannerList = async () => {
  const res = await http<BannerItem[]>({
    method: 'GET',
    url: '/home/banner' // 无需拼接基础地址
  })
  console.log('首页轮播图数据:', res.result)
}

// 执行请求
getBannerList()

三、首页核心功能:自定义导航栏(适配多机型)

1. 配置隐藏默认导航栏(pages.json)

TypeScript 复制代码
{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationStyle": "custom", // 隐藏默认导航栏
        "navigationBarTextStyle": "white", // 文字颜色(隐藏后仍需配置,影响状态栏)
        "navigationBarTitleText": "首页"
      }
    }
  ]
}

2. 自定义导航栏组件(适配安全区域)

TypeScript 复制代码
<template>
  <!-- 自定义导航栏:适配不同机型安全区域 -->
  <view class="navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }">
    <view class="navbar-title">小兔鲜儿 | 新鲜·亲民·快捷</view>
    <view class="search-bar">
      <uni-icons type="search" size="16" color="#999"></uni-icons>
      <text class="search-text">搜索商品</text>
    </view>
  </view>
</template>

<script setup>
// 获取系统信息:安全区域距离(适配iPhone刘海屏等)
const { safeAreaInsets } = uni.getSystemInfoSync()
</script>

<style scoped>
.navbar {
  background-color: #27BA9B;
  padding-bottom: 12rpx;
}
.navbar-title {
  color: white;
  font-size: 18px;
  font-weight: bold;
  text-align: center;
  margin-bottom: 8rpx;
}
.search-bar {
  display: flex;
  align-items: center;
  background-color: white;
  border-radius: 30rpx;
  padding: 8rpx 16rpx;
  margin: 0 16rpx;
}
.search-text {
  margin-left: 8rpx;
  font-size: 14px;
  color: #999;
}
</style>

3. 核心适配逻辑

  • safeAreaInsets.top:获取状态栏到安全区域的距离,避免内容被刘海屏遮挡
  • 导航栏背景色与全局样式统一(#27BA9B),保持视觉一致性
  • 搜索栏使用uni-icons组件(uni-ui 内置),无需额外引入

四、关键注意事项

  1. 接口请求必须添加source-client: miniapp请求头,否则服务端可能拒绝响应
  2. Token 失效(401 状态码)时,需清空用户信息并强制跳转登录页
  3. 静态资源必须放在static目录下,否则 uni-app 无法正确识别
  4. 开发 TS 项目时,务必安装对应的类型声明文件,避免类型报错
  5. 微信开发者工具需开启「服务端口」,否则 HBuilderX/VS Code 无法编译预览
相关推荐
刘发财13 小时前
弃用html2pdf.js,这个html转pdf方案能力是它的几十倍
前端·javascript·github
牛奶15 小时前
2026年大模型怎么选?前端人实用对比
前端·人工智能·ai编程
牛奶15 小时前
前端人为什么要学AI?
前端·人工智能·ai编程
Kagol18 小时前
🎉OpenTiny NEXT-SDK 重磅发布:四步把你的前端应用变成智能应用!
前端·开源·agent
GIS之路19 小时前
ArcGIS Pro 中的 notebook 初识
前端
JavaGuide19 小时前
7 道 RAG 基础概念知识点/面试题总结
前端·后端
ssshooter20 小时前
看完就懂 useSyncExternalStore
前端·javascript·react.js
格砸20 小时前
从入门到辞职|从ChatGPT到OpenClaw,跟上智能时代的进化
前端·人工智能·后端
Live0000021 小时前
在鸿蒙中使用 Repeat 渲染嵌套列表,修改内层列表的一个元素,页面不会更新
前端·javascript·react native
柳杉21 小时前
使用Ai从零开发智慧水利态势感知大屏(开源)
前端·javascript·数据可视化