【商城实战(25)】解锁UniApp移动端适配秘籍,打造完美商城体验

【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配,乃至运营推广策略,102 章内容层层递进。无论是想深入钻研技术细节,还是探寻商城运营之道,本专栏都能提供从 0 到 1 的系统讲解,助力你打造独具竞争力的电商平台,开启电商实战之旅。

目录

  • 一、UniApp 适配移动端设备原理及实现
    • 1.1 适配原理
    • 1.2 实现源码展示
  • 二、利用响应式布局实现页面自适应
    • 2.1 响应式布局功能介绍
    • 2.2 实现源码示例
  • 三、解决移动端常见适配问题
    • 3.1 刘海屏适配
    • 3.2 实现源码
    • 3.3 虚拟按键适配
    • 3.4 实现源码展示


一、UniApp 适配移动端设备原理及实现

1.1 适配原理

UniApp 适配不同移动端设备的核心原理是利用条件编译和相对单位,以及弹性布局等技术。

  • 条件编译:UniApp 允许开发者使用特殊的注释语法来区分不同平台的代码。例如,通过#ifdef和#endif指令,开发者可以编写特定平台的代码块。#ifdef APP-PLUS表示只有在 App 平台下才会编译该代码块,#ifdef H5则表示只在 H5 平台编译。这样可以针对手机、平板等不同设备的特性,编写专门的逻辑,比如调用特定设备的 API。
  • 相对单位:在处理不同屏幕尺寸时,使用相对单位如rpx(responsive pixel)至关重要。rpx会根据屏幕宽度进行自适应,规定屏幕宽度为 750rpx。在 iPhone6 上,屏幕宽度为 375px,此时 1rpx = 0.5px 。这样,使用rpx作为单位设置元素的尺寸,能够在不同屏幕尺寸的设备上保持相对一致的布局和显示效果,避免因屏幕尺寸差异导致的布局错乱 。
  • 弹性布局:采用 Flexbox 弹性布局模型,它能够自动调整元素的大小和位置,以适应不同的屏幕尺寸和方向。通过设置display: flex,可以方便地实现水平或垂直方向的布局,并且可以控制元素的伸缩比例、对齐方式等,使得页面在各种设备上都能呈现出合理的布局。

1.2 实现源码展示

假设我们有一个商品列表页面,需要从 Spring Boot 后端获取数据并展示,同时确保在不同设备上都能正确适配。

首先,在 Spring Boot 后端定义一个获取商品列表的接口:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;@RestController
public class ProductController {@GetMapping("/products")public List<Product> getProducts() {List<Product> productList = new ArrayList<>();// 这里可以从数据库查询数据,示例中简单构造数据Product product1 = new Product(1, "商品1", "描述1", 10.0);Product product2 = new Product(2, "商品2", "描述2", 20.0);productList.add(product1);productList.add(product2);return productList;}
}class Product {private int id;private String name;private String description;private double price;public Product(int id, String name, String description, double price) {this.id = id;this.name = name;this.description = description;this.price = price;}// 省略getter和setter方法
}

在 UniApp 前端页面中,使用uni.request获取数据,并通过弹性布局和rpx单位进行页面布局:

<template><view class="product-list"><view class="product-item" v-for="(product, index) in products" :key="index"><view class="product-name">{{ product.name }}</view><view class="product-description">{{ product.description }}</view><view class="product-price">价格: {{ product.price }}</view></view></view>
</template><script>
export default {data() {return {products: []};},onLoad() {this.getProducts();},methods: {getProducts() {uni.request({url: 'http://localhost:8080/products', // 根据实际情况修改method: 'GET',success: res => {this.products = res.data;},fail: err => {console.log('获取数据失败', err);}});}}
};
</script><style scoped>
.product-list {display: flex;flex-direction: column;padding: 20rpx;
}.product-item {background-color: #f5f5f5;border-radius: 10rpx;padding: 15rpx;margin-bottom: 15rpx;display: flex;flex-direction: column;
}.product-name {font-size: 20rpx;font-weight: bold;margin-bottom: 10rpx;
}.product-description {font-size: 16rpx;color: #666;margin-bottom: 10rpx;
}.product-price {font-size: 18rpx;color: #f00;
}
</style>

在上述代码中,通过uni.request向 Spring Boot 后端发送请求获取商品数据。页面布局使用了 Flexbox 弹性布局,使商品列表以垂直方向排列,并且使用rpx作为单位设置元素的尺寸和间距,以确保在不同设备上都能有良好的显示效果。同时,通过v-for指令循环渲染商品数据到页面上。

二、利用响应式布局实现页面自适应

2.1 响应式布局功能介绍

UniApp 的响应式布局功能基于 Vue.js 的响应式原理,能够根据屏幕尺寸的变化自动调整页面元素的位置和大小。这一功能主要通过以下几种方式实现:

  • Flex 布局:Flexbox 布局模型是实现响应式布局的重要手段。通过设置display: flex,可以将容器内的子元素按照灵活的方式排列。例如,可以通过flex-direction属性控制子元素是水平排列(row)还是垂直排列(column);justify-content属性用于控制子元素在主轴上的对齐方式,如center(居中对齐)、space-between(两端对齐)等;align-items属性则控制子元素在交叉轴上的对齐方式。
  • 媒体查询:虽然 UniApp 在小程序端不支持传统的 CSS 媒体查询,但在 H5 端可以使用。媒体查询允许根据设备的屏幕宽度、高度、分辨率等特性来应用不同的样式。例如,可以使用@media screen and (max-width: 600px)来针对屏幕宽度小于 600px 的设备应用特定的样式,实现页面在小屏幕设备上的优化布局。
  • 自适应单位:除了前面提到的rpx单位,UniApp 还支持vw(视窗宽度百分比)和vh(视窗高度百分比)等自适应单位。1vw等于视窗宽度的 1%,1vh等于视窗高度的 1%。使用这些单位可以使元素的尺寸根据视窗大小进行动态调整,从而实现响应式布局。比如,设置一个元素的宽度为50vw,那么在任何设备上,该元素都会占据视窗宽度的一半。

2.2 实现源码示例

以下是一个利用响应式布局实现商品详情页面自适应的示例,该页面从 Spring Boot 后端通过 MyBatis - Plus 获取商品数据并展示。

首先,在 Spring Boot 后端定义获取商品详情的接口,假设商品实体类为Product,数据库表名为product,使用 MyBatis - Plus 进行数据查询:

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.demo.entity.Product;
import com.example.demo.mapper.ProductMapper;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class ProductController {private final ProductMapper productMapper;public ProductController(ProductMapper productMapper) {this.productMapper = productMapper;}@GetMapping("/products/{id}")public Product getProductById(@PathVariable Integer id) {QueryWrapper<Product> queryWrapper = new QueryWrapper<>();queryWrapper.eq("id", id);return productMapper.selectOne(queryWrapper);}
}

在 UniApp 前端页面中,使用uni.request获取数据,并通过 Flex 布局和媒体查询实现响应式布局:

<template><view class="product-detail"><image :src="product.imageUrl" mode="aspectFill" class="product-image"></image><view class="product-info"><view class="product-title">{{ product.name }}</view><view class="product-price">价格: {{ product.price }}</view><view class="product-description">{{ product.description }}</view></view></view>
</template><script>
export default {data() {return {product: {}};},onLoad(options) {const productId = options.id;this.getProductDetails(productId);},methods: {getProductDetails(id) {uni.request({url: `http://localhost:8080/products/${id}`, // 根据实际情况修改method: 'GET',success: res => {this.product = res.data;},fail: err => {console.log('获取数据失败', err);}});}}
};
</script><style scoped>
.product-detail {display: flex;flex-direction: column;
}.product-image {width: 100%;height: 300rpx;
}.product-info {padding: 20rpx;
}.product-title {font-size: 24rpx;font-weight: bold;margin-bottom: 10rpx;
}.product-price {font-size: 20rpx;color: #f00;margin-bottom: 10rpx;
}.product-description {font-size: 16rpx;color: #666;
}/* 媒体查询,针对小屏幕设备调整布局 */
@media screen and (max-width: 480px) {.product-image {height: 200rpx;}.product-title {font-size: 20rpx;}.product-price {font-size: 18rpx;}.product-description {font-size: 14rpx;}
}
</style>

在上述代码中,通过uni.request获取商品详情数据,并在页面加载时根据商品 ID 请求数据。页面布局使用 Flex 布局,使图片和商品信息垂直排列。通过媒体查询,当屏幕宽度小于 480px 时,调整图片高度和文字大小,以适应小屏幕设备的显示,确保在不同屏幕尺寸下都能提供良好的用户体验。同时,使用rpx单位保证在不同设备上的相对尺寸一致性。

三、解决移动端常见适配问题

3.1 刘海屏适配

随着全面屏手机的普及,刘海屏手机越来越常见。刘海屏的出现给移动端应用的界面布局带来了挑战,因为屏幕顶部的刘海区域会遮挡页面内容,影响用户体验。在 UniApp 中,适配刘海屏的关键在于正确处理安全区域,确保页面内容不会被刘海遮挡 。安全区域是指屏幕上不会被刘海、圆角或虚拟按键等影响的区域。通过合理设置页面元素的边距和布局,使其在安全区域内显示,可以有效解决刘海屏适配问题。

3.2 实现源码

首先,在manifest.json文件的app-plus节点下进行安全区域配置:

{"app-plus": {"safearea": {"bottom": {"offset": "auto"}}}
}

上述配置中,safearea.bottom.offset设置为auto,表示自动计算底部安全区域偏移,确保页面内容不会被底部的操作区域遮挡。

在页面样式中,使用安全区域变量来设置元素的内边距,例如:

.page {padding-top: constant(safe-area-inset-top);padding-top: env(safe-area-inset-top);padding-bottom: constant(safe-area-inset-bottom);padding-bottom: env(safe-area-inset-bottom);
}

这里使用constant(safe-area-inset-top)和env(safe-area-inset-top)来设置页面顶部的内边距,constant(safe-area-inset-bottom)和env(safe-area-inset-bottom)来设置页面底部的内边距。constant用于兼容 iOS 12.0 - 12.1 版本,env用于兼容 iOS 11.0 - 11.4 版本 。通过这种方式,页面内容在刘海屏手机上能够正确显示,不会被刘海或底部操作区域遮挡。

3.3 虚拟按键适配

虚拟按键的出现也会对页面布局产生影响,尤其是当虚拟按键弹出或收起时,页面元素的位置和大小可能需要动态调整,以避免被虚拟按键遮挡或覆盖,保证用户界面的完整性和可用性 。在 UniApp 中,适配虚拟按键主要通过监听虚拟按键的状态变化,并根据状态动态调整页面元素的样式和布局。

3.4 实现源码展示

以下是一个监听虚拟按键状态并动态调整页面底部按钮位置的示例代码:

<template><view class="container"><view class="content"><!-- 页面主体内容 --></view><view class="bottom-button" :style="{ bottom: buttonBottom + 'px' }" @click="handleClick">按钮</view></view>
</template><script>
export default {data() {return {buttonBottom: 0};},onLoad() {this.initVirtualKeyListener();},methods: {initVirtualKeyListener() {uni.onKeyboardHeightChange(res => {if (res.height === 0) {// 虚拟按键隐藏this.buttonBottom = 0;} else {// 虚拟按键弹出this.buttonBottom = res.height;}});},handleClick() {// 按钮点击逻辑}}
};
</script><style scoped>
.container {position: relative;height: 100vh;
}.content {padding: 20rpx;
}.bottom-button {position: fixed;left: 0;width: 100%;height: 80rpx;line-height: 80rpx;text-align: center;background-color: #007aff;color: #fff;
}
</style>

在上述代码中,通过uni.onKeyboardHeightChange方法监听虚拟按键的高度变化。当虚拟按键隐藏时(res.height === 0),将按钮的bottom样式属性设置为 0;当虚拟按键弹出时,将按钮的bottom样式属性设置为虚拟按键的高度res.height,从而实现按钮位置的动态调整,确保按钮不会被虚拟按键遮挡,保证页面在虚拟按键出现时仍能正常展示和交互。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/72297.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《C++ Primer》学习笔记(二)

第二部分&#xff1a;C标准库 1.为了支持不同种类的IO处理操作&#xff0c;标准库定义了以下类型的IO&#xff0c;分别定义在三个独立的文件中&#xff1a;iostream文件中定义了用于读写流的基本类型&#xff1b;fstream文件中定义了读写命名文件的类型&#xff1b;sstream文件…

MATLAB风光柴储微网粒子群算法

本程序实现了风光柴储微网中的粒子群优化&#xff08;PSO&#xff09;算法&#xff0c;用于优化微网的能源调度问题。具体来说&#xff0c;程序考虑了光伏发电、风力发电、柴油机发电&#xff08;柴储&#xff09;&#xff0c;并使用粒子群算法来优化这些能源的调度&#xff0c…

解决Windows版Redis无法远程连接的问题

&#x1f31f; 解决Windows版Redis无法远程连接的问题 在Windows系统下使用Redis时&#xff0c;很多用户会遇到无法远程连接的问题。尤其是在配置了Redis并尝试通过工具如RedisDesktopManager连接时&#xff0c;可能会报错“Cannot connect to ‘redisconnection’”。今天&am…

解决 HTTP 请求中的编码问题:从乱码到正确传输

文章目录 解决 HTTP 请求中的编码问题&#xff1a;从乱码到正确传输1. **问题背景**2. **乱码问题的原因**2.1 **客户端编码问题**2.2 **请求头缺失**2.3 **服务器编码问题** 3. **解决方案**3.1 **明确指定请求体编码**3.2 **确保请求头正确**3.3 **动态获取响应编码** 4. **调…

VS Code 配置优化指南

目录 一、安装与基础设置1. 安装 VS Code2. 中文语言包 二、插件推荐三、常见配置项与优化1. 用户 / 工作区设置2. 全局配置 / Settings Sync3. 常用设置示例 四、性能优化五、调试与终端配置1. 调试配置2. 内置终端配置 六、快捷键配置七、美观与主题八、总结 VS Code&#xf…

基于NXP+FPGA永磁同步电机牵引控制单元(单板结构/机箱结构)

永磁同步电机牵引控制单元&#xff08;单板结构/机箱结构&#xff09; 永磁同步电机牵引控制单元&#xff08;TCU-PMSM&#xff09;用于牵引逆变器-永磁同步电机构成的牵引电传动系统&#xff0c;采用轴控方式。执行高性能永磁同步电机复矢量控制策略&#xff0c;具有响应迅速…

/etc/sysconfig/jenkins 没有这个文件

在 CentOS 或其他基于 Red Hat 的 Linux 系统中&#xff0c;/etc/sysconfig/jenkins 文件通常用来存储 Jenkins 的配置参数&#xff0c;例如 JENKINS_HOME 的路径。但是&#xff0c;如果你发现没有这个文件&#xff0c;你可以通过以下几种方式来解决或确认&#xff1a; 检查 J…

conda 安装软件报错 Found conflicts! Looking for incompatible packages.

问题描述&#xff1a; 利用 conda 安装某包 conda install -c "nvidia/label/cuda-11.8.0" cuda-nvcc时发现报错&#xff1a; Collecting package metadata (current_repodata.json): done Solving environment: failed with initial frozen solve. Retrying with…

MySQL 衍生表(Derived Tables)

在SQL的查询语句select …. from …中&#xff0c;跟在from子句后面的通常是一张拥有定义的实体表&#xff0c;而有的时候我们会用子查询来扮演实体表的角色&#xff0c;这个在from子句中的子查询会返回一个结果集&#xff0c;这个结果集可以像普通的实体表一样查询、连接&…

STM32配套程序接线图

1 工程模板 2 LED闪烁 3LED流水灯 4蜂鸣器 5按键控制LED 6光敏传感器控制蜂鸣器 7OLED显示屏 8对射式红外传感器计次 9旋转编码器计次 10 定时器定时中断 11定时器外部时钟 12PWM驱动LED呼吸灯 13 PWM驱动舵机 14 PWM驱动直流电机 15输入捕获模式测频率 16PWMI模式测频率占空…

鸿蒙初级考试备忘

Module类型 Module按照使用场景可以分为两种类型&#xff1a; Ability类型的Module&#xff1a; 用于实现应用的功能和特性。每一个Ability类型的Module编译后&#xff0c;会生成一个以.hap为后缀的文件&#xff0c;我们称其为HAP&#xff08;Harmony Ability Package&#x…

语音识别踩坑记录

本来想在原来的语音识别的基础上增加本地扩展本地词典&#xff0c; 采用的语音识别是Vosk识别器&#xff0c;模型是 vosk-model-small-cn-0.22 // 初始化Vosk识别器 if (recognizer null) {using (Model model new Model(modelPath)){string grammar "{""…

SpringCloud 学习笔记1(Spring概述、工程搭建、注册中心、负载均衡、 SpringCloud LoadBalancer)

文章目录 SpringCloudSpringCloud 概述集群和分布式集群和分布式的区别和联系 微服务什么是微服务&#xff1f;分布式架构和微服务架构的区别微服务的优缺点&#xff1f;拆分微服务原则 什么是 SpringCloud &#xff1f;核心功能与组件 工程搭建父项目的 pom 文件 注册中心Rest…

计算机网络-网络规划与设计

基本流程 需求分析—》通信规范分析—》逻辑网络设计—》物理网络设计—》实施阶段 需求分析&#xff1a; 确定需求&#xff0c;包括&#xff1a;业务需求、用户需求、应用需求、计算机平台需求、网络通信需求等。 产物&#xff1a;需求规范 通信规范分析&#xff1a; 现有…

《AI浪潮中的璀璨新星:Meta Llama、Ollama与DeepSeek的深度剖析》:此文为AI自动生成

《AI浪潮中的璀璨新星&#xff1a;Meta Llama、Ollama与DeepSeek的深度剖析》&#xff1a;此文为AI自动生成 引言&#xff1a;AI 大模型的群雄逐鹿时代 在科技飞速发展的当下&#xff0c;AI 大模型领域已成为全球瞩目的焦点&#xff0c;竞争激烈程度堪称白热化。从 OpenAI 推出…

基础知识《HTTP字段与状态码详细说明》

HTTP 协议字段与状态码完整指南 一、HTTP 字段&#xff08;请求头与响应头&#xff09; HTTP 头字段用于传递客户端和服务器之间的元数据&#xff0c;分为 请求头&#xff08;Request Headers&#xff09; 和 响应头&#xff08;Response Headers&#xff09;。 1. 常见请求头…

DeepSeek linux服务器(CentOS)部署命令笔记

Linux&#xff08;CentOS&#xff09;FinalShellOllama远程访问&#xff0c;本地部署deepseek 自备CentOS服务器&#xff0c;并且已经使用FinalShell连接到服务器 一、准备工作 1.更新服务器 apt-get update-y 2.下载Ollama curl -fsSL https://ollama.com/install.sh | …

C#通过API接口返回流式响应内容---分块编码方式

1、背景 上一篇文章《C#通过API接口返回流式响应内容—SSE方式》阐述了通过SSE&#xff08;Server Send Event&#xff09;方式&#xff0c;由服务器端推送数据到浏览器。本篇是通过分块编码的方式实现 2、效果 3、具体代码 3.1 API端实现 [HttpGet] public async Task Chu…

SSL 原理及实验

引言 为了实现远程办公或者远程客户访问内网的资源 &#xff08;1&#xff09;回顾历史&#xff1a; 起初先出现SSL(Secure Sockets Layer&#xff09;&#xff0d;安全套接层协议。 美国网景Netscape公司1994年研发&#xff0c;介于传输层TCP协议和应用层协议之间的一种协议…

C++ 布尔类型(bool)深度解析

引言 在 C 编程里&#xff0c;布尔类型&#xff08;bool&#xff09;是一种基础且极为关键的数据类型。它专门用于表达逻辑值&#xff0c;在程序的条件判断、循环控制等诸多方面都发挥着重要作用。接下来&#xff0c;我们将对 C 中的布尔类型展开全面且深入的探讨。 一、布尔…