当前位置: 首页 > news >正文

uniapp 基础(三)

目录

1.uniapp 如何实现表单验证?

内置组件

自定义函数

第三方验证库

实时表单验证

结合UI组件库

后端验证的必要性

2.不同平台的导航栏差异

导航栏基础配置

条件编译

JS控制导航栏

复杂导航栏处理

微信小程序胶囊按钮适配

自定义导航栏组件

状态栏高度适配

注意事项

3.小程序的自定义 tabBar

配置 manifest.json 文件

创建自定义 tabBar 组件

实现 tabBar 逻辑

同步页面路径与选中状态

 处理页面生命周期

4.uniapp 状态管理 方法

全局变量

Vuex 状态管理

Pinia 替代方案

本地存储与持久化

Vuex 推荐场景

5.跨平台分享功能

使用uni.share API

平台差异处理

自定义分享按钮

分享到更多平台

注意事项

6.小程序图片上传

uni.chooseImage选择图片

上传图片到服务器

多图上传处理

图片压缩与预览

注意事项

7.UniApp使用 WebSocket

WebSocket 基础配置

监听 WebSocket 事件

发送消息

关闭 WebSocket 连接

断线重连机制

注意事项

示例

8.UniApp 如何支持 PWA

配置 manifest.json

修改项目配置

生成 Service Worker

构建项目

9.UniApp 中如何处理用户授权

检查权限状态

请求权限

处理拒绝授权后的引导

获取用户位置

兼容多端差异

注意事项

10. UniApp 的插件机制,如何集成一个地图插件

UniApp 插件机制概述

集成地图插件的步骤

选择地图插件

配置插件

调用插件功能

注意事项


1.uniapp 如何实现表单验证?

内置组件

uniapp的<form>组件和<input>组件支持基础的表单验证。可以设置required属性进行非空验证,或通过type属性限制输入类型(如emailnumber)。

<form @submit="handleSubmit"><input v-model="formData.username" required placeholder="请输入用户名" /><input v-model="formData.password" type="password" required placeholder="请输入密码" /><button form-type="submit">提交</button>
</form>

自定义函数

通过JavaScript编写验证逻辑,在提交表单时触发验证函数。例如验证手机号格式:

第三方验证库

async-validator 可以简化复杂验证规则的实现

import Schema from 'async-validator';const rules = {username: { type: 'string', required: true, message: '用户名不能为空' },email: { type: 'email', message: '邮箱格式不正确' }
};const validator = new Schema(rules);methods: {validateForm() {validator.validate(this.formData, (errors) => {if (errors) {uni.showToast({ title: errors[0].message, icon: 'none' });} else {// 提交表单}});}
}

实时表单验证

通过监听输入变化实现实时验证,提升用户体验

<input v-model="formData.email" @input="validateEmail" placeholder="邮箱" />
methods: {validateEmail() {const reg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;if (!reg.test(this.formData.email)) {this.errorMsg = '邮箱格式不正确';} else {this.errorMsg = '';}}
}

结合UI组件库

使用uViewuni-ui等组件库提供的表单验证功能,可以快速实现带错误提示的验证。以uView为例:

<u-form :model="formData" :rules="rules" ref="uForm"><u-form-item label="用户名" prop="username"><u-input v-model="formData.username" /></u-form-item>
</u-form>
data() {return {rules: {username: [{ required: true, message: '请输入用户名', trigger: 'blur' }]}};
},
methods: {submit() {this.$refs.uForm.validate(valid => {if (valid) {// 验证通过}});}
}

后端验证的必要性

前端验证无法替代后端验证。在提交数据到服务器后,必须进行后端验证以确保数据安全性。前端验证仅用于提升用户体验和减少无效请求。

2.不同平台的导航栏差异

导航栏基础配置

pages.json 中配置全局导航栏样式,通过 globalStyle 统一基础属性,例如背景色、文字颜色。针对特定页面,在 style 节点中覆盖全局配置。

"globalStyle": {"navigationBarTextStyle": "black","navigationBarTitleText": "默认标题","navigationBarBackgroundColor": "#FFFFFF"
},
"pages": [{"path": "page/index","style": {"navigationBarTitleText": "自定义标题"}
}]

条件编译

pages.json 或组件中,通过 #ifdef#endif 区分不同平台代码块。

"style": {"navigationBarTitleText": "通用标题","#ifdef H5": {"navigationStyle": "custom"  // H5隐藏默认导航栏},"#ifdef APP-PLUS": {"titleNView": {              // APP专用配置"buttons": [{"text": "按钮","fontSize": "16px"}]}}
}

JS控制导航栏

通过 uni.setNavigationBarTitleuni.setNavigationBarColor 动态修改导航栏属性。

注意:部分API在小程序不兼容

// 修改标题
uni.setNavigationBarTitle({title: '新标题'
});// 修改背景色(仅支持HEX)
uni.setNavigationBarColor({frontColor: '#000000',backgroundColor: '#FF0000'
});

复杂导航栏处理

在 titleNView 配置复杂导航栏,支持按钮、搜索框等组件。需在 pages.json 中声明:

"titleNView": {"searchInput": {"align": "center","backgroundColor": "#F5F5F5","borderRadius": "4px"},"buttons": [{"text": "\ue534","fontSrc": "/static/iconfont.ttf","fontSize": "22px"}]
}

微信小程序胶囊按钮适配

通过 uni.getMenuButtonBoundingClientRect() 获取胶囊按钮位置信息,动态计算偏移量

const menuInfo = uni.getMenuButtonBoundingClientRect();
console.log(menuInfo.width, menuInfo.top); // 示例:自定义导航栏高度计算
const statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
const navHeight = menuInfo.top + menuInfo.height + 8;

自定义导航栏组件

创建跨平台导航栏组件,通过 slot 接收内容,内部处理平台差异:

<template><view class="custom-nav"><!-- 安卓/iOS返回按钮 --><view v-if="showBack" @click="handleBack"><text class="icon-back"></text></view><slot></slot></view>
</template><script>
export default {computed: {showBack() {return uni.getSystemInfoSync().platform !== 'h5';}},methods: {handleBack() {uni.navigateBack();}}
}
</script>

状态栏高度适配

使用 uni.getSystemInfoSync() 获取状态栏高度,确保内容不被遮挡:

const systemInfo = uni.getSystemInfoSync();
const statusBarHeight = systemInfo.statusBarHeight || 0;
const navBarHeight = systemInfo.platform === 'android' ? 48 : 44;
const totalHeight = statusBarHeight + navBarHeight;

注意事项

  • 微信小程序自定义导航栏需在 pages.json 设置 "navigationStyle": "custom"
  • APP端动态修改导航栏按钮需使用 uni.setNavigationBarButton
  • H5端隐藏导航栏可能影响浏览器原生返回功能
  • 颜色值需使用6位HEX格式(如 #RRGGBB),不支持缩写或RGB

3.小程序的自定义 tabBar

配置 manifest.json 文件

在项目的 manifest.json 文件中,明确声明需要使用自定义 tabBar。找到对应的小程序配置项(如微信小程序),添加以下配置:

"mp-weixin": {"tabBar": {"custom": true}
}

创建自定义 tabBar 组件

 在项目根目录下创建 custom-tab-bar 文件夹,内部结构需符合小程序规范。通常包含以下文件:

  • index.vue(或 index 目录下的组件文件)
  • 相关样式和逻辑文件

实现 tabBar 逻辑

custom-tab-bar/index.vue 中,通过 Vue 语法实现交互逻辑。例如:

<template><div class="custom-tab-bar"><div v-for="(item, index) in list" :key="index" @click="switchTab(index)">{{ item.text }}</div></div>
</template><script>
export default {data() {return {list: [{ text: "首页", pagePath: "/pages/index/index" },{ text: "分类", pagePath: "/pages/category/index" }]};},methods: {switchTab(index) {uni.switchTab({ url: this.list[index].pagePath });}}
};
</script>

同步页面路径与选中状态

 在 pages.json 中配置原生 tabBar 的路径(仅作参考,实际渲染由自定义组件控制):

"tabBar": {"list": [{ "pagePath": "pages/index/index" },{ "pagePath": "pages/category/index" }]
}

 处理页面生命周期

在页面 onShow 生命周期中更新 tabBar 选中状态:

onShow() {if (typeof this.getTabBar === 'function' && this.getTabBar()) {this.getTabBar().setData({ selected: 0 }); // 根据实际索引调整}
}

4.uniapp 状态管理 方法

全局变量

App.vue 中定义全局变量,通过 getApp().globalData 访问。适合简单数据共享,但不支持响应式更新。

// App.vue
export default {globalData: { count: 0 }
}
// 页面中使用
const app = getApp()
console.log(app.globalData.count)

Vuex 状态管理

Vuex 是 Vue 生态的集中式状态管理工具,适合复杂应用。UniApp 支持 Vuex,需在项目根目录创建 store 文件夹并配置。

// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)export default new Vuex.Store({state: { count: 0 },mutations: { increment(state) { state.count++ } }
})
// 页面中使用
import { mapState, mapMutations } from 'vuex'
export default {computed: { ...mapState(['count']) },methods: { ...mapMutations(['increment']) }
}

Pinia 替代方案

Pinia 是 Vuex 的轻量级替代,支持 Composition API,TypeScript 友好。UniApp 可通过插件引入。

// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {state: () => ({ count: 0 }),actions: { increment() { this.count++ } }
})
// 页面中使用
import { useCounterStore } from '@/stores/counter'
export default {setup() {const counter = useCounterStore()return { counter }}
}

本地存储与持久化

结合 uni.setStorageSync 实现状态持久化,适合需长期保存的数据。

// 存储状态
uni.setStorageSync('userToken', 'abc123')
// 读取状态
const token = uni.getStorageSync('userToken')

Vuex 推荐场景

  • 推荐使用:跨多个页面共享复杂状态,需严格的同步更新机制。
  • 不推荐场景:简单应用或仅需父子组件通信时,优先使用 Props/Emit 或全局变量。

Vuex 会增加项目复杂度,建议根据实际需求评估。对于小型项目,Pinia 或全局变量可能更高效。

5.跨平台分享功能

UniApp提供了统一的API,支持微信、QQ、微博等主流社交平台的分享功能。

使用uni.share API

UniApp内置的uni.share API可以轻松实现多平台分享。该API支持微信、QQ、新浪微博等平台。

uni.share({provider: "weixin", // 分享服务提供商,可选值:weixin、qq、sinaweibo等scene: "WXSceneSession", // 分享到聊天界面(WXSceneSession)或朋友圈(WXSceneTimeline)type: 0, // 分享类型,0为图文,1为纯文字,2为图片,5为小程序title: "分享标题",summary: "分享内容摘要",href: "https://example.com", // 分享链接imageUrl: "https://example.com/image.png", // 分享图片success: function(res) {console.log("分享成功");},fail: function(err) {console.log("分享失败", err);}
});

平台差异处理

不同平台对分享的支持程度不同,需根据平台特性调整参数。例如,微信支持分享到朋友圈和聊天界面,而QQ仅支持分享到聊天界面。

// 判断平台并设置不同参数
let provider = "";
let scene = "";// #ifdef MP-WEIXIN
provider = "weixin";
scene = "WXSceneSession"; // 或 WXSceneTimeline
// #endif// #ifdef MP-QQ
provider = "qq";
// #endifuni.share({provider: provider,scene: scene,// 其他参数
});

自定义分享按钮

某些平台(如微信小程序)要求分享必须通过按钮触发,不能直接调用API。需要在页面中添加<button>组件并设置open-type="share"

<button open-type="share" type="warn">点击分享</button>

在页面的onShareAppMessage生命周期中定义分享内容:

onShareAppMessage() {return {title: "自定义分享标题",path: "/pages/index/index",imageUrl: "/static/logo.png"};
}

分享到更多平台

如果需要分享到更多平台(如微博、支付宝等),可以通过条件编译或第三方插件扩展功能。

// #ifdef APP-PLUS
// 使用原生扩展或第三方SDK
const share = uni.requireNativePlugin("ShareModule");
share.shareToWeibo({text: "分享到微博",image: "/static/logo.png"
});
// #endif

注意事项

  • 分享功能在某些平台(如微信)需要配置合法域名。
  • 部分平台要求应用审核通过后才能使用分享功能。
  • 图片链接需为HTTPS协议,且某些平台对图片大小有限制。

6.小程序图片上传

uni.chooseImage选择图片

调用uni.chooseImage接口选择本地图片,支持多选和压缩。

uni.chooseImage({count: 3, // 最多选择3张sizeType: ['compressed'], // 压缩图success: (res) => {const tempFilePaths = res.tempFilePaths // 临时文件路径数组}
})

上传图片到服务器

获取临时路径后,通过uni.uploadFile上传。需注意小程序端需配置合法域名:

uni.uploadFile({url: 'https://example.com/upload',filePath: tempFilePaths[0],name: 'file',formData: { user: 'test' },success: (uploadRes) => {console.log(uploadRes.data);}
})

多图上传处理

递归上传方法 采用递归方式依次上传多张图片,确保顺序执行:

function uploadFiles(files, index = 0) {if (index >= files.length) returnuni.uploadFile({url: 'https://example.com/upload',filePath: files[index],success: () => {uploadFiles(files, index + 1)}})
}

图片压缩与预览

使用条件编译处理平台差异 通过#ifdef区分平台,H5端可用canvas压缩:

// #ifdef H5
compressImage(path) {// H5端压缩逻辑
}
// #endif

预览大图接口 调用uni.previewImage实现预览功能:

uni.previewImage({current: 0, // 当前显示索引urls: imageList // 图片URL数组
})

注意事项

域名白名单配置 小程序需在后台配置requestuploadFile的合法域名,开发阶段可勾选不校验域名。

临时路径有效期 小程序端获取的临时路径仅在本次启动有效,不可直接存储。需上传成功后保存服务器返回的永久URL。

类型限制示例 通过extension参数限制文件类型:

uni.chooseImage({extension: ['jpg', 'png'] // 只允许选择jpg/png
})

7.UniApp使用 WebSocket

WebSocket 基础配置

在 UniApp 中使用 WebSocket 需要通过 uni.connectSocket 方法建立连接。

const socketTask = uni.connectSocket({url: 'wss://your-websocket-server.com',success: () => {console.log('WebSocket 连接成功');},fail: (err) => {console.error('WebSocket 连接失败', err);}
});

监听 WebSocket 事件

WebSocket 支持多个事件监听,包括连接打开、接收消息、错误和关闭事件。通过 uni.onSocketOpenuni.onSocketMessage 等方法实现:

uni.onSocketOpen((res) => {console.log('WebSocket 连接已打开');
});uni.onSocketMessage((res) => {console.log('收到服务器内容:', res.data);
});uni.onSocketError((err) => {console.error('WebSocket 错误:', err);
});uni.onSocketClose((res) => {console.log('WebSocket 连接已关闭');
});

发送消息

通过 uni.sendSocketMessage 方法向服务器发送消息:

uni.sendSocketMessage({data: JSON.stringify({ message: 'Hello WebSocket' }),success: () => {console.log('消息发送成功');},fail: (err) => {console.error('消息发送失败', err);}
});

关闭 WebSocket 连接

通过 uni.closeSocket 方法主动关闭连接:

uni.closeSocket({success: () => {console.log('WebSocket 连接已关闭');}
});

断线重连机制

为实现稳定性,可以加入断线重连的逻辑。以下是一个简单的实现:

let reconnectAttempts = 0;
const maxReconnectAttempts = 5;function connectWebSocket() {const socketTask = uni.connectSocket({url: 'wss://your-websocket-server.com',success: () => {reconnectAttempts = 0;},fail: () => {if (reconnectAttempts < maxReconnectAttempts) {setTimeout(connectWebSocket, 3000);reconnectAttempts++;}}});
}uni.onSocketClose(() => {if (reconnectAttempts < maxReconnectAttempts) {setTimeout(connectWebSocket, 3000);reconnectAttempts++;}
});

注意事项

  • 协议支持:确保服务器支持 WebSocket 协议(ws://wss://)。
  • 多平台兼容性:部分小程序平台对 WebSocket 的实现可能有差异,需测试目标平台。
  • 心跳机制:长时间连接建议加入心跳包防止超时断开。
  • 全局管理:建议将 WebSocket 逻辑封装为单独模块以便复用。

示例

class WebSocketManager {constructor(url) {this.url = url;this.socketTask = null;this.reconnectAttempts = 0;this.maxReconnectAttempts = 5;}connect() {this.socketTask = uni.connectSocket({url: this.url,success: () => {this.reconnectAttempts = 0;},fail: () => this.handleReconnect()});this.setupEventListeners();}setupEventListeners() {uni.onSocketOpen(() => {console.log('WebSocket connected');});uni.onSocketMessage((res) => {console.log('Received:', res.data);});uni.onSocketClose(() => {this.handleReconnect();});}handleReconnect() {if (this.reconnectAttempts < this.maxReconnectAttempts) {setTimeout(() => this.connect(), 3000);this.reconnectAttempts++;}}send(data) {uni.sendSocketMessage({data: JSON.stringify(data)});}close() {uni.closeSocket();}
}// 使用示例
const ws = new WebSocketManager('wss://your-websocket-server.com');
ws.connect();

8.UniApp 如何支持 PWA

UniApp 通过特定的配置和插件可以将应用打包为 PWA(Progressive Web App),

配置 manifest.json

在项目根目录创建 manifest.json 文件,内容参考以下示例:

{"name": "My PWA App","short_name": "PWA App","start_url": ".","display": "standalone","background_color": "#ffffff","theme_color": "#4DBA87","icons": [{"src": "static/icons/icon-192x192.png","sizes": "192x192","type": "image/png"},{"src": "static/icons/icon-512x512.png","sizes": "512x512","type": "image/png"}]
}

修改项目配置

manifest.json 同目录下创建 vue.config.js,配置 PWA 插件:

module.exports = {pwa: {name: 'My PWA App',themeColor: '#4DBA87',msTileColor: '#000000',appleMobileWebAppCapable: 'yes',appleMobileWebAppStatusBarStyle: 'black',manifestPath: 'manifest.json',workboxPluginMode: 'GenerateSW',workboxOptions: {skipWaiting: true,clientsClaim: true}}
}

生成 Service Worker

UniApp 使用 Workbox 生成 Service Worker。确保项目中已安装 workbox-webpack-plugin

npm install workbox-webpack-plugin --save-dev

构建项目

运行以下命令生成 PWA 所需的文件:

npm run build

构建完成后,dist 目录会包含 sw.jsmanifest.json 等 PWA 必需文件。

部署注意事项

  • 必须通过 HTTPS 协议访问 PWA 应用。
  • 确保服务器正确配置 Content-Typeapplication/json 处理 manifest.json
  • 测试 PWA 功能可使用 Chrome 的 Lighthouse 工具。

9.UniApp 中如何处理用户授权

检查权限状态

在 UniApp 中,可以使用 uni.getSetting 检查用户是否已授权某项权限。该方法返回用户的授权状态,可通过 authSetting 对象判断具体权限是否开启。

uni.getSetting({success(res) {const hasLocationPermission = res.authSetting['scope.userLocation']if (hasLocationPermission) {console.log('用户已授权位置权限')} else {console.log('用户未授权位置权限')}}
})

请求权限

如果用户未授权,通过 uni.authorize 发起权限请求。需在 manifest.json 中声明所需权限(如 "requiredPrivateInfos": ["getLocation"])。

uni.authorize({scope: 'scope.userLocation',success() {console.log('授权成功')},fail() {console.log('授权失败')}
})

处理拒绝授权后的引导

用户可能首次拒绝授权,需通过 uni.openSetting 引导用户手动开启权限

uni.showModal({title: '提示',content: '需要位置权限才能继续使用,是否去设置开启?',success(res) {if (res.confirm) {uni.openSetting({success(res) {console.log('用户已跳转至设置页')}})}}
})

获取用户位置

授权成功后,调用 uni.getLocation 获取具体位置信息。需注意高精度模式(isHighAccuracy)可能增加耗电量。

uni.getLocation({type: 'wgs84',success(res) {console.log('经度:', res.longitude, '纬度:', res.latitude)},fail(err) {console.error('获取位置失败:', err)}
})

兼容多端差异

不同平台(微信小程序、H5、App)的权限机制可能不同:

  • 微信小程序:需通过 button 组件的 open-type="openSetting" 触发跳转设置页。
  • H5:依赖浏览器 API(如 navigator.geolocation),需处理 HTTPS 环境限制。
  • App:需在原生配置文件中声明权限(如 Android 的 AndroidManifest.xml)。

注意事项

  • 频繁调用授权弹窗可能被平台限制,建议合理设计触发逻辑。
  • 部分平台(如 iOS)要求提供权限使用目的描述,需在配置文件中补充隐私说明。
  • 用户拒绝后,部分平台(如微信小程序)需等待 24 小时才能再次触发授权弹窗。

10. UniApp 的插件机制,如何集成一个地图插件

UniApp 插件机制概述

UniApp 的插件机制允许开发者扩展原生功能,通过集成原生插件实现跨平台能力(如调用设备硬件、地图、支付等)。插件分为两种类型:

  • 原生插件:基于 Android/iOS 原生代码开发,需通过 UniApp 的插件市场或手动集成。
  • JS 插件:纯前端实现,基于 JavaScript 的通用功能扩展。

插件通过 uni.requireNativePlugin 或直接引入 JS 模块的方式调用。


集成地图插件的步骤

选择地图插件

UniApp 官方推荐的高德地图或腾讯地图插件,可通过插件市场搜索并下载。以高德地图为例:

配置插件
  1. 引入插件包
    下载插件后,将插件包(如 amap-uni-plugin)放入项目根目录的 nativeplugins 文件夹。

  2. 配置 manifest.json
    manifest.jsonApp原生插件配置 中添加插件:

    "app-plus": {"plugins": {"amap": {"version": "x.x.x", // 插件版本"provider": "dcloud.amap"}}
    }
    
  3. 配置平台密钥
    在高德开放平台申请 AppKey,并填入 manifest.json

    "app-plus": {"distribute": {"android": {"amap": {"appkey": "你的高德Android Key"}},"ios": {"amap": {"appkey": "你的高德iOS Key"}}}
    }
    
调用插件功能

在页面中通过原生插件 API 调用地图功能:

const amap = uni.requireNativePlugin('amap');
amap.init(() => {console.log('地图初始化成功');
});
// 打开地图页面
amap.openMap({latitude: 39.90469,longitude: 116.40717,name: '北京市'
});

注意事项

  • 平台差异:Android 和 iOS 需分别配置密钥和权限。
  • 调试:真机调试时需确保原生插件已正确打包到安装包中。
  • 更新插件:插件版本需与 UniApp SDK 兼容,定期检查更新。

http://www.lryc.cn/news/609610.html

相关文章:

  • weapp-tailwindcss 已支持 uni-app x 多端构建
  • uniapp基础(四)性能优化
  • 使用opencv基于realsense D435i展示基本的图像
  • 计算机网络:有路由器参与的子网间通信原理
  • 阿里云与华为云产品的差异
  • 计算机网络:网络号和网络地址的区别
  • OpenCV轻松入门_面向python(第二章图像处理基础)
  • 从物理扇区到路径访问:Linux文件抽象的全景解析
  • Linux 网络深度剖析:传输层协议 UDP/TCP 原理详解
  • iostat 系统IO监控命令学习
  • 二叉树的概念以及二叉树的分类,添加,删除
  • OpenCV计算机视觉实战(18)——视频处理详解
  • Postman:配置环境变量
  • 【Unity3D实例-功能-镜头】第三人称视觉
  • VUE2 学习笔记17 路由
  • 算法训练营DAY50 第十一章:图论part01
  • 代码随想录day55图论5
  • [spring-cloud: 负载均衡]-源码分析
  • 软件设计 VS 软件需求:了解成功软件开发外包的关键差异
  • 【数据结构入门】链表
  • Centos7.9安装Oracle11.2.0.1版本问题处理
  • Python实现Word转PDF全攻略:从入门到实战
  • 电商直播流量爆发式增长,华为云分布式流量治理与算力调度服务的应用场景剖析
  • windows内核研究(软件调试-软件断点)
  • 房屋租赁小程序租房小程序房产信息发布系统房屋租赁微信小程序源码
  • 架构师面试(三十九):微服务重构单体应用
  • 剧本杀小程序系统开发:开启沉浸式推理社交新纪元
  • 力扣1124:表现良好的最长时间段
  • 【Java】使用FreeMarker来实现Word自定义导出
  • leetcode-sql-3497分析订阅转化