python兼职网站开发,网站建设现状,天眼查企业查询官网登录入口,广州 科技网站建设公司Uni APP的学习
官方文档
uni-app官网 (dcloud.net.cn)
任何的博客都不如官方文档
一、快速复习
文件结构
main.js
功能#xff1a;项目的入口文件#xff0c;初始化 Vue 实例。 App.vue功能#xff1a;根组件#xff0c;包含应用的基本结构和全局样式。 manifest.js…Uni APP的学习
官方文档
uni-app官网 (dcloud.net.cn)
任何的博客都不如官方文档
一、快速复习
文件结构
main.js
功能项目的入口文件初始化 Vue 实例。 App.vue功能根组件包含应用的基本结构和全局样式。 manifest.json功能应用的全局配置文件包含应用名称、图标、平台特定配置等信息。 pages.json功能配置应用的页面路由、导航栏、选项卡等信息。 uni.scss功能全局的 SCSS 样式文件可以在整个项目中使用。 components/功能用于存放项目中的可复用组件。 pages/功能用于存放项目的页面每个页面通常有一个独立的目录和对应的 .vue 文件。 static/功能用于存放项目中的静态资源如图片、字体等。 uni_modules/功能用于存放 UniApp 插件模块。 store/功能用于存放 Vuex 状态管理的相关文件。 utils/功能用于存放工具函数和公共方法。 unpackage/功能用于存放编译后的文件和生成的包。包含生成的各个平台的编译文件是项目发布和运行的产物目录
为什么每个页面都使用template包围
每个页面都是一个组件
在 UniApp 中一个页面本质上是一个独立的 Vue 组件。它包含了自己的 template、script 和 style因此可以独立运行。由于 Vue 组件的特性这些页面也可以在其他地方被当作子组件使用。 组件复用你可以将一个页面或组件嵌套在另一个页面或组件中复用其内容和逻辑。例如你可以在一个主页面中引入一个通用的头部或底部组件。通过在不同页面之间复用组件你可以保持代码的简洁并减少重复劳动。 组件之间的通信当你将一个页面作为组件嵌套在另一个页面中时你可以通过 props 传递数据或者通过事件 $emit 和 $on 来实现父子组件之间的通信。这使得页面之间可以互相传递数据形成一个有机的整体。
view标签
view 标签在 UniApp 中是一个非常重要且常用的标签。它在 UniApp 中起到了类似于 HTML 中 div 标签的作用用于构建页面的基本布局和结构。下面是对 view 标签的详细讲解
1. 基本功能
view 标签是 UniApp 中的一个容器元素用来包含其他的视图元素或者组件。你可以将 view 标签理解为一个通用的布局容器类似于 HTML 中的 div 标签。
2. 属性
view 标签支持很多属性下面是一些常见的属性
class: 用于为 view 添加样式类通过 CSS 进行样式控制。style: 直接内联样式设置例如 stylemargin:10px; padding:5px;。id: 为 view 指定唯一标识符用于在 JS 代码中进行操作。hover-class: 当用户触摸时会给 view 添加的样式类。hover-start-time: 按住时长达到多少毫秒才显示 hover 状态默认 50 毫秒。hover-stay-time: 手指松开后保留 hover 状态的时长默认 400 毫秒。
3. 使用示例
下面是一个简单的示例展示如何使用 view 标签来构建一个页面的布局
template!-- 页面根容器使用 Flex 布局来组织页面结构 --view classcontainer!-- 头部区域 --view classheader !-- 应用样式类 header --hover-classhover-effect !-- 用户触摸时应用 hover-effect 样式 --text这是头部带有hover效果/text !-- 显示在头部的文本内容 --/view!-- 主要内容区域带有点击事件 --view classcontent !-- 应用样式类 content --clickhandleClick !-- 点击时触发 handleClick 方法 --hover-classhover-effect !-- 用户触摸时应用 hover-effect 样式 --hover-start-time100 !-- 用户触摸 100 毫秒后开始显示 hover 效果 --hover-stay-time300 !-- 松开触摸后hover 效果持续 300 毫秒 --idmain-content !-- 设置唯一标识符为 main-content --text点击这里触发事件/text !-- 显示在内容区域的文本内容 --/view!-- 底部区域使用动态内联样式 --view classfooter !-- 应用样式类 footer --stylebackground-color: #00aaff; !-- 内联样式设置背景颜色为蓝色 --:style{ height: dynamicHeight px } !-- 动态设置高度使用 Vue 的绑定语法 --text这是底部背景颜色通过style设置/text !-- 显示在底部的文本内容 --/view/view
/templatescript
export default {data() {return {dynamicHeight: 50 // 动态设置底部区域的高度为 50 像素};},methods: {handleClick() {// 点击事件的处理逻辑console.log(内容区域被点击);}}
};
/scriptstyle
/* 容器的样式设置为 Flex 布局子元素按垂直方向排列容器高度占满页面 */
.container {display: flex; /* 启用弹性布局 */flex-direction: column; /* 子元素垂直排列从上到下 */height: 100%; /* 容器高度占满父容器或视口 */
}/* 头部的样式 */
.header {background-color: #f8f8f8; /* 设置背景颜色为浅灰色 */padding: 10px; /* 内边距为 10 像素 */text-align: center; /* 文本居中对齐 */
}/* 内容区域的样式 */
.content {flex: 1; /* 占据容器中剩余的所有空间 */background-color: #ffffff; /* 设置背景颜色为白色 */padding: 20px; /* 内边距为 20 像素 */
}/* 底部的样式 */
.footer {padding: 10px; /* 内边距为 10 像素 */text-align: center; /* 文本居中对齐 */
}/* 用户触摸时的 hover 效果样式 */
.hover-effect {background-color: #e0e0e0; /* 设置触摸时的背景颜色为浅灰色 */
}
/style
在这个例子中
hover-class: 作用为 view 组件添加一个在用户触摸时显示的样式类。通常用于按钮或可点击的区域提供视觉反馈。示例hover-classhover-effect当用户点击或触摸时hover-effect 样式会被应用。 hover-start-time:作用设置用户触摸多少毫秒后开始显示 hover-class。示例hover-start-time100用户触摸 100 毫秒后开始显示 hover-class 的效果。 hover-stay-time:作用设置用户松开触摸后hover-class 的效果持续多久毫秒。示例hover-stay-time300在用户松开触摸后hover-class 的效果会持续 300 毫秒。 id:作用为 view 组件设置唯一的标识符可以用于在 JS 中进行 DOM 操作。示例idmain-content你可以通过 this.$refs[main-content] 来引用这个元素。 style:作用内联样式直接应用于 view 元素用于设置动态样式。示例stylebackground-color: #00aaff; 为 view 设置了蓝色背景。 :style{ height: dynamicHeight px } 使用 Vue 的动态绑定来设置高度。 click:作用绑定点击事件当 view 被点击时触发对应的事件处理函数。示例clickhandleClick点击 content 区域时将调用 handleClick 方法。 class:作用应用定义在 style 中的样式类用于控制 view 的外观和布局。示例classheader 应用了 .header 中定义的样式。
4. 为什么使用 view 而不是 div
跨平台支持: view 标签在所有 UniApp 支持的平台上都可以正常使用而 div 是 HTML 元素不适用于小程序、App 等其他平台。性能优化: UniApp 对 view 标签做了许多平台优化可以更好地适应移动端设备提供更流畅的用户体验。样式控制: view 标签内的样式和布局在不同平台之间更一致使用 view 可以减少跨平台开发时的样式兼容性问题。
5. 常见的使用场景
布局容器: 创建页面的基础结构和布局。点击区域: 配合 hover-class 等属性实现点击效果。数据展示: 包裹和组织其他元素如文本、图片、列表等.
flex布局
1. 基础概念
Flex 容器Flex Container: 包含子元素Flex 项目的父容器通常通过设置 display: flex; 来定义。Flex 项目Flex Items: 容器内的所有直接子元素它们将自动成为弹性布局的一部分可以自由地根据容器的规则进行排列和对齐。
2. 基本属性
在 Flexbox 布局中最重要的属性主要有以下几类
2.1. 容器属性应用于 Flex 容器
display: flex; 将一个元素定义为 Flex 容器容器内的子元素将变成 Flex 项目。 flex-direction 决定 Flex 项目的排列方向。 row: 默认值从左到右水平排列。row-reverse: 从右到左水平排列。column: 从上到下垂直排列。column-reverse: 从下到上垂直排列。 justify-content 控制 Flex 项目在主轴flex-direction 方向的对齐方式。 flex-start: 靠主轴的起点对齐。flex-end: 靠主轴的终点对齐。center: 居中对齐。space-between: 项目之间的间距相等首尾项目与容器边缘对齐。space-around: 项目之间的间距相等项目和容器边缘之间留有一半的间距。 align-items 控制 Flex 项目在交叉轴与主轴垂直的方向的对齐方式。 stretch: 默认值项目在交叉轴方向上拉伸以填充容器。flex-start: 靠交叉轴的起点对齐。flex-end: 靠交叉轴的终点对齐。center: 在交叉轴方向居中对齐。baseline: 项目基线对齐。 flex-wrap 决定如果容器空间不足Flex 项目是否换行。 nowrap: 默认值不换行。wrap: 换行项目在多行中排列。wrap-reverse: 反向换行。
2.2. 项目属性应用于 Flex 项目
flex 简写属性用于指定 Flex 项目的可伸缩性。 flex: 1; 表示项目将占据容器的所有可用空间多个项目之间将按比例分配空间。 align-self 允许单个项目对齐方式与容器的 align-items 属性不同。 order 控制项目的排列顺序数值越小的项目会排在前面默认值为 0
二、websocket的连接
函数介绍
1. connect
功能建立 WebSocket 连接并设置各种事件回调来处理连接成功、收到消息、连接关闭和连接出错的情况。核心操作通过 uni.connectSocket 方法创建 WebSocket 连接成功后发送初始数据。
2. sendMessage
功能通过 WebSocket 连接向服务器发送文本消息。核心操作 检查 WebSocket 连接是否处于打开状态。构造要发送的消息包含目标客户端 ID 和消息内容。通过 socketTask.send 方法发送消息。
3. handleFileChange
功能处理用户选择的音频文件并将文件保存在组件的状态中以便稍后发送。核心操作 捕获用户选择的文件并将其存储在 audioFile 变量中。
4. sendAudio
功能将选择的音频文件通过 WebSocket 连接发送给服务器。核心操作 使用 FileReader 读取音频文件的内容并转换为 ArrayBuffer 格式。 通过 socketTask.send 方法逐块发送音频数据并在发送结束后发送 EOF 标志表示文件传输结束。
详细功能介绍
1. connect
功能启动 WebSocket 连接是整个应用程序的核心功能。它确保了客户端能够与服务器通信并在连接成功后立即向服务器发送客户端的身份信息即 uniqueId 和 mateUniqueId。使用场景当用户想要连接到服务器进行实时通信时点击“Connect”按钮触发。
2. sendMessage
功能允许用户通过 WebSocket 连接向特定的客户端发送消息。这是聊天应用或任何需要发送点对点消息的应用程序的核心功能。使用场景当用户输入目标客户端 ID 和消息内容后点击“Send”按钮发送消息。
3. handleFileChange
功能捕获用户选择的音频文件并为后续的音频传输做准备。这个函数确保了音频文件能够正确读取并保存在组件的状态中。使用场景当用户选择音频文件时这个函数被触发准备好文件以便稍后发送。
4. sendAudio
功能将音频文件通过 WebSocket 连接发送到服务器。这个函数负责处理音频文件的分块传输并确保传输的完整性。使用场景当用户选择了音频文件并点击“Send Audio”按钮时触发这个函数开始传输音频数据。
连接函数
connect() {// 创建一个 WebSocket 连接保存到 socketTask 变量中this.socketTask uni.connectSocket({url: wss://erroright.cn/ws, // WebSocket 服务器的地址success: () {// 如果 WebSocket 连接创建成功输出成功日志console.log(WebSocket connection created.);},fail: (error) {// 如果 WebSocket 连接创建失败输出错误信息console.error(Failed to create WebSocket connection:, error);}});// 当 WebSocket 连接成功时触发的事件回调this.socketTask.onOpen(() {// 输出调试信息表示已经成功连接到 WebSocket 服务器console.log(Connected to WebSocket server.);// 构造发送给服务器的初始数据包含客户端的唯一 ID 和配对客户端的唯一 IDlet data {send_id: this.uniqueId, // 客户端的唯一 IDreceive_id: this.mateUniqueId // 配对客户端的唯一 ID};// 输出调试信息显示即将发送的初始数据console.log(Sending initial data:, data);// 通过 WebSocket 连接发送初始数据this.socketTask.send({data: JSON.stringify(data), // 将数据转换为 JSON 字符串格式发送fail: (error) {// 如果发送初始数据失败输出错误信息console.error(Failed to send initial data:, error);}});});// 当从服务器接收到消息时触发的事件回调this.socketTask.onMessage((event) {// 输出调试信息显示接收到的消息内容console.log(Received message from server:, event.data);// 将接收到的消息添加到 messages 数组中以便在页面中显示this.messages.push(event.data);});// 当 WebSocket 连接关闭时触发的事件回调this.socketTask.onClose(() {// 输出调试信息表示 WebSocket 连接已关闭console.log(Disconnected from WebSocket server.);});// 当 WebSocket 连接出错时触发的事件回调this.socketTask.onError((error) {// 输出调试信息显示具体的错误内容console.error(WebSocket error occurred:, error);});
}发送信息
sendMessage() {// 检查 WebSocket 连接是否存在并且处于打开状态if (this.socketTask this.socketTask.readyState WebSocket.OPEN) {// 构造要发送的消息对象包含目标客户端 ID 和消息内容let message JSON.stringify({content: this.messageText // 要发送的消息内容});// 输出调试信息显示即将发送的消息内容console.log(Sending message:, message);// 通过 WebSocket 连接发送消息this.socketTask.send({data: message, // 发送的消息数据success: () {// 发送成功后清空消息输入框this.messageText ;},fail: (error) {// 如果消息发送失败输出错误信息console.error(Failed to send message:, error);}});} else {// 如果 WebSocket 未连接或状态不正确输出错误信息console.error(WebSocket is not connected or is in an invalid state.);}},捕获音频文件为后续音频传输做准备
handleFileChange(event) {// 从事件对象 event 中获取用户选择的文件// event.target.files 是一个 FileList 对象包含了用户选择的所有文件// [0] 代表获取第一个文件对象因为通常用户只选择一个文件this.audioFile event.target.files[0];// 输出调试信息显示用户选择的文件的名称// 通过 this.audioFile.name 获取文件的名称确认用户选择的文件正确无误console.log(Selected audio file:, this.audioFile.name);
}发送音频文件给服务器
sendAudio() {// 检查是否选择了音频文件if (!this.audioFile) {// 如果没有选择音频文件提示用户先选择文件uni.showToast({title: Please select an audio file first, // 显示的提示信息icon: none // 不显示图标});return; // 结束函数执行}// 创建一个 FileReader 对象用于读取文件内容let reader new FileReader();// 定义 FileReader 的 onload 回调当文件读取完成时触发reader.onload (event) {// 获取读取的文件内容作为 ArrayBuffer 对象let arrayBuffer event.target.result;// 将 ArrayBuffer 转换为 Uint8Array这样可以逐字节处理数据let bytes new Uint8Array(arrayBuffer);// 输出调试信息显示即将发送的音频数据console.log(Sending audio data:, bytes);// 通过 WebSocket 发送音频数据this.socketTask.send({data: bytes.buffer, // 将 Uint8Array 的缓冲区发送success: () {// 音频数据发送成功后再发送一个 EOF 标志表示传输结束this.socketTask.send({data: EOF, // 发送 EOF 表示文件传输结束success: () {console.log(EOF sent.); // 输出 EOF 发送成功的日志},fail: (error) {console.error(Failed to send EOF:, error); // 输出 EOF 发送失败的错误信息}});},fail: (error) {console.error(Failed to send audio data:, error); // 输出音频数据发送失败的错误信息}});};// 开始异步读取音频文件的内容并将其转换为 ArrayBuffer 格式reader.readAsArrayBuffer(this.audioFile);
}
三、蓝牙
1. initBlue
功能初始化蓝牙模块。操作 调用 uni.openBluetoothAdapter 打开蓝牙适配器。 如果初始化成功调用 startBluetoothDevicesDiscovery 开始搜索蓝牙设备。
2. startBluetoothDevicesDiscovery
功能启动蓝牙设备的搜索。操作 调用 uni.startBluetoothDevicesDiscovery 开始搜索蓝牙设备。 如果搜索成功设置蓝牙设备发现的回调函数 onBluetoothDeviceFound。
3. onBluetoothDeviceFound
功能处理发现的蓝牙设备。操作 当发现蓝牙设备时检查设备名称是否与 deviceName 匹配。 如果匹配保存设备的 deviceId 并调用 createBLEConnection 尝试连接设备。
4. createBLEConnection
功能创建蓝牙低功耗设备 (BLE) 的连接。操作 调用 uni.createBLEConnection 连接到指定的蓝牙设备。如果连接成功更新连接状态为已连接 (isConnected: true)。延迟 3 秒后调用 getBLEDeviceServices 获取设备的服务列表。
5. getBLEDeviceServices
功能获取连接设备的服务列表。操作 调用 uni.getBLEDeviceServices 获取设备的服务。如果成功遍历服务列表并检查是否包含指定的服务 UUID (SERVICE_UUID)。如果找到匹配的服务调用 getBLEDeviceCharacteristics 获取该服务的特性。如果获取服务失败或服务列表为空最多重试三次。
6. getBLEDeviceCharacteristics
功能获取指定服务的特性。操作 调用 uni.getBLEDeviceCharacteristics 获取服务的特性列表。如果成功检查特性是否支持写操作并将其 UUID 保存到 CHARACTERISTIC_UUID。如果没有找到支持写操作的特性输出错误信息。
7. sendDataToBluetooth
功能发送数据到蓝牙设备。操作 首先检查是否已连接到蓝牙设备。 如果连接正常调用 sendDataInChunks 将数据分块发送到蓝牙设备。
8. sendDataInChunks
功能将数据分块发送到蓝牙设备。操作 根据设备的 MTU 大小这里假设为 517 字节将数据分块。 对每个数据块创建 ArrayBuffer 并转换为字节数据后通过 uni.writeBLECharacteristicValue 发送给设备。
9. action
功能发送 “over” 命令到蓝牙设备表示数据传输完成或其他特定操作。操作 类似于 sendDataToBluetooth但是这里发送的是 “over” 字符串。
templateview classcontainerview classintro蓝牙消息发送示例。/viewbutton clickinitBlue连接蓝牙/buttonbutton clicksendDataToBluetooth发送数据/buttonbutton clickaction开始运行/button/view
/templatescriptexport default {data() {return {deviceName: MiniBay, // 要连接的设备名称deviceId: null, // 设备 IDSERVICE_UUID: 4FAFC201-1FB5-459E-8FCC-C5C9C331914B, // 服务的 UUID (大写)CHARACTERISTIC_UUID: BEB5483E-36E1-4688-B7F5-EA07361B26A8, // 特性的 UUID (大写)dataToSend:{10, 10, 200},{20, 10, 200},{10, 20, 200},{30, 10, 200},{25, 25, 100},{10, 30, 200},{20, 20, 100},{30, 30, 100},{35, 35, 100},{40, 40, 100},{45, 45, 100},{50, 50, 100},{55, 55, 100},{60, 60, 100},{65, 65, 100},{70, 70, 100},{75, 75, 100},{80, 80, 100},{85, 85, 200},{90, 90, 200},{95, 95, 200},{90, 90, 200},{95, 95, 200},{90, 90, 200},{95, 95, 200},{90, 90, 200},{95, 95, 200},{90, 90, 200},{95, 95, 200},{90, 90, 200},{95, 95, 200},{90, 90, 200},{45, 45, 200},{0, 0, 0},isConnected: false // 用于跟踪蓝牙是否已连接}},methods: {initBlue() {uni.openBluetoothAdapter({success: res {console.log(初始化蓝牙成功);this.startBluetoothDevicesDiscovery();},fail: err {console.log(初始化蓝牙失败);console.error(err);}});},startBluetoothDevicesDiscovery() {uni.startBluetoothDevicesDiscovery({success: res {console.log(开始搜索设备...);this.onBluetoothDeviceFound();},fail: err {console.log(搜索设备失败);console.error(err);}});},onBluetoothDeviceFound() {uni.onBluetoothDeviceFound(devices {devices.devices.forEach(device {if (device.name this.deviceName) {console.log(找到设备:, device);this.deviceId device.deviceId;this.createBLEConnection();}});});},createBLEConnection() {if (this.deviceId) {uni.createBLEConnection({deviceId: this.deviceId,success: res {console.log(连接设备成功);this.isConnected true; // 更新连接状态// 延迟以确保设备服务准备就绪setTimeout(() {this.getBLEDeviceServices();}, 3000);},fail: err {console.log(连接设备失败);this.isConnected false; // 确保连接失败时状态更新console.error(err);}});}},getBLEDeviceServices(retryCount 0) {uni.getBLEDeviceServices({deviceId: this.deviceId,success: res {if (res.services res.services.length 0) {console.log(获取服务成功:, res.services);res.services.forEach((service, index) {console.log(服务 ${index 1}: UUID ${service.uuid});});// 检查是否找到特定的服务const service res.services.find(s s.uuid this.SERVICE_UUID);if (service) {this.getBLEDeviceCharacteristics(service.uuid);} else {console.error(未找到指定的服务);}} else {console.error(服务列表为空或未找到服务);if (retryCount 3) { // 尝试重试三次console.log(重试获取服务 (${retryCount 1}/3));setTimeout(() {this.getBLEDeviceServices(retryCount 1);}, 3000); // 每次延迟3秒再重试}}},fail: err {console.log(获取服务失败);console.error(err);}});},getBLEDeviceCharacteristics(serviceId) {uni.getBLEDeviceCharacteristics({deviceId: this.deviceId,serviceId: serviceId,success: res {console.log(获取特性成功:, res.characteristics);// 检查特性是否支持写操作const writableCharacteristic res.characteristics.find(char char.properties.write);if (writableCharacteristic) {this.CHARACTERISTIC_UUID writableCharacteristic.uuid;} else {console.error(未找到支持写操作的特性);}},fail: err {console.log(获取特性失败);console.error(err);}});},sendDataToBluetooth() {if (!this.isConnected) {console.error(未连接到蓝牙设备);return;}const data this.dataToSend;this.sendDataInChunks(data);},sendDataInChunks(data) {const maxChunkSize 517; // 依据设备的 MTU20 是默认蓝牙包大小for (let i 0; i data.length; i maxChunkSize) {const chunk data.slice(i, i maxChunkSize);const buffer new ArrayBuffer(chunk.length);const dataView new DataView(buffer);for (let j 0; j chunk.length; j) {dataView.setUint8(j, chunk.charCodeAt(j));}uni.writeBLECharacteristicValue({deviceId: this.deviceId,serviceId: this.SERVICE_UUID,characteristicId: this.CHARACTERISTIC_UUID,value: buffer,success: res {console.log(数据发送成功:, chunk);},fail: err {console.log(数据发送失败);console.error(err);}});}},action() {if (!this.isConnected) {console.error(未连接到蓝牙设备);return;}const formattedData over;const buffer new ArrayBuffer(formattedData.length);const dataView new DataView(buffer);for (let i 0; i formattedData.length; i) {dataView.setUint8(i, formattedData.charCodeAt(i));}uni.writeBLECharacteristicValue({deviceId: this.deviceId,serviceId: this.SERVICE_UUID,characteristicId: this.CHARACTERISTIC_UUID,value: buffer,success: res {console.log(数据发送成功:, formattedData);},fail: err {console.log(数据发送失败);console.error(err);}});}}}
/scriptstyle.container {padding: 20px;font-size: 14px;line-height: 24px;}
/style