h5开发心得

news/2024/9/19 8:04:48/文章来源:https://www.cnblogs.com/hxy--Tina/p/18316687

运营推广移动端开发

1.适配原理

宽的适配:flexible.js适配,是根据屏幕的宽度计算根标签的大小进行适配,
高的适配

  • 需要用vh,vh在静态页面好用,vh是根据屏幕的可视高度计算的,当页面中有输入框时vh的页面会受到挤压,如下图
  • 用百分比

2.移动端布局

  • 如果有按钮,最好让ui设计到一个层级上不要用相对定位,固定定位,因为软键盘弹起会顶起按钮,按钮会遮挡内容。
  • 尽量少用相对定位固定定位,因为不能滚动,在小屏上无法解决适配问题。

3.安卓软键盘引起的问题

1.软键盘打开会顶起页面,造成页面超出,输入框被遮挡问题。

解决方案:用resize事件监听窗口的高度变化,根据窗口变化调整页面样式高度。

// 定义一个函数来处理窗口大小变化时的逻辑function checkViewportSize() {// // 获取当前窗口的高度var windowHeight = window.innerHeight;// 更新窗口高度记录initialWindowHeight = windowHeight;}// 记录初始窗口高度var initialWindowHeight = window.innerHeight;// 初始化时调用一次,确保页面加载时也能记录初始窗口高度checkViewportSize();// 监听窗口大小变化事件,并在事件发生时调用处理函数window.addEventListener('resize', checkViewportSize);

2.软键盘弹起按钮被顶起问题

解决方式:根据窗口变化,让按钮显示隐藏

// 定义一个函数来处理窗口大小变化时的逻辑function checkViewportSize() {// 获取当前窗口的高度var windowHeight = window.innerHeight;// 判断当前窗口高度是否小于之前记录的高度if (windowHeight < initialWindowHeight) {// 可能是软键盘弹起导致的高度变小,执行你需要的逻辑console.log('软键盘弹起,可视区域变小');// 例如隐藏特定元素或调整布局$('.tabBox').hide()} else {// 可能是软键盘收起导致的高度变大,执行其他逻辑console.log('软键盘收起,可视区域恢复');// 例如显示特定元素或恢复布局$('.tabBox').show()}// 更新窗口高度记录initialWindowHeight = windowHeight;}// 记录初始窗口高度var initialWindowHeight = window.innerHeight;// 初始化时调用一次,确保页面加载时也能记录初始窗口高度checkViewportSize();// 监听窗口大小变化事件,并在事件发生时调用处理函数window.addEventListener('resize', checkViewportSize);

4.ios软件盘打开页面留白问题。

解决方案:输入框失焦window.scrollTo(0, 0);

$('#staffCode').blur(function () {setTimeout(() => {window.scrollTo(0, 0);}, 100);})

5.上拉加载

实现原理:

scrollTop:滚动视窗的高度距离window顶部的距离,它会随着往上滚动而不断增加,初始值是0,它是一个变化的值

clientHeight:它是一个定值,表示屏幕可视区域的高度;

scrollHeight:页面不能滚动时也是存在的,此时scrollHeight等于clientHeight。scrollHeight表示body所有元素的总长度(包括body元素
自身的padding)

判断是否滚动到底部的公式:scrollTop+clientHeight>=srcollHeight

触发上拉加载的时机
1.滚动到底部=》scrollTop+clientHeight>=srcollHeight
2.滚动条不在顶部
=》scrollTop!==0
3.不在刷新,
4.不在加载
5.没加载完

   $('#middle').scroll(function () {var content = this// 内容的总高度contentHeight = content.scrollHeight// 可视区域的高度viewportHeight = content.clientHeight// 当前滚动的位置scrollTop = content.scrollTop;scrollBottom = contentHeight - (scrollTop + viewportHeight);// 判断是否在顶部var atTop = scrollTop === 0;// 检查是否滚动到底部// 这里的2作为一个阈值,可以根据需要调整if (scrollBottom <= 100 && scrollBottom >= 0 && !isLoading && !isRefreshing && !atTop && !allDataLoaded) {// 到达底部,可以执行加载更多数据的操作console.log("到达底部");getItemList();}});

示例:

var page = 1;
var size = 10;
var isRefreshing = false;
var isLoading = false;
var allDataLoaded = false;//调用:
$('#list').html('');
page = 1;
allDataLoaded = false
getBuildList()function getItemList() {if (isLoading && isRefreshing && allDataLoaded) returnisLoading = true;$('#loading').show();$('#noData').hide();var result = '';if (xhr) {xhr.abort();}xhr = $.ajax({url: getAuthorizedGroup,type: 'post',async: true,data: {"staffCode": staffCode,"page": page,"size": size},dataType: 'json',success: function (res) {if (res.status == 1) {if (res.data.status == 1) {let items = res.data.rows.map(i => {return {...i,buildCount: i.buildCount == -1 ? '全部电站' : i.buildCount + ' 个'};});var arrLen = items.length;if (arrLen > 0) {for (var i = 0; i < arrLen; i++) {result += drawHtml(items[i]);}page++;if (arrLen < 10) {$('#loading').hide();$('#noData').show();}} else {$('#loading').hide();allDataLoaded = true; // 所有数据已加载完毕if (page == 1) {result = `<div class='imgBox'><img src="./img/noActivity.png" alt="未找到推广活动"></div>`} else {$('#noData').show();}}} else {alert(res.data.msg)}} else {alert(res.data)}$('#list').append(result);isLoading = false;},error: function (xhr) {console.log("🚀 ~ getItemList ~ xhr:", xhr)isLoading = false;},});}

6.下拉刷新

触发上拉刷新的时机:
1.滚动条在顶部,scrollTop==0

2.touchstart事件(e.touches[0].clientY),touchend(e.changedTouches[0].clientY)结束距离-开始距离>0(向上滑动)

刷新注意事项:
刷新时page定死为1,全局的page 定为2,这样就不会出现,刷新后,滚动时page还是1,出现数据重复数据问题。

  var isRefreshing = false;var isLoading = false;var allDataLoaded = false;var xhr;var startY = 0; // 记录触摸开始时的Y坐标document.addEventListener('touchstart', function (e) {startY = e.touches[0].clientY;});document.addEventListener('touchend', function (e) {var endY = e.changedTouches[0].clientY;var atTop = $("#middle").scrollTop() === 0; // 注意使用 scrollTop() 方法来获取滚动距离var distance = endY - startY;if (Math.abs(distance) > 50 && atTop) {if (distance > 0) {$("#list").html('');allDataLoaded = false;refreshItemList(); // 在实际应用中,根据实际情况处理数据加载 }}});document.addEventListener('touchcancel', function (e) {var endY = e.changedTouches[0].clientY;var atTop = $("#middle").scrollTop() === 0; // 注意使用 scrollTop() 方法来获取滚动距离var distance = endY - startY;if (Math.abs(distance) > 50 && atTop) {if (distance > 0) {$("#list").html('');allDataLoaded = false;refreshItemList(); // 在实际应用中,根据实际情况处理数据加载 }}});function refreshItemList() {if (isRefreshing && isLoading) returnisRefreshing = true;$('#refresh').show();$('#loading').hide();$('#noData').hide();var result = '';// 取消之前的未完成请求if (xhr) {xhr.abort();}xhr = $.ajax({url: getAuthorizedGroup,type: 'post',async: true,data: {"staffCode": staffCode,"page": 1,"size": size},dataType: 'json',success: function (res) {if (res.status == 1) {if (res.data.status == 1) {$('#refresh').hide();let items = res.data.rows.map(i => {return {...i,buildCount: i.buildCount == -1 ? '全部电站' : i.buildCount + ' 个'};});var arrLen = items.length;if (arrLen > 0) {for (var i = 0; i < arrLen; i++) {result += drawHtml(items[i]);}if (arrLen < 10) {$('#noData').show();}page = 2;} else {if (page == 1) {result = `<div class='imgBox'><img src="./img/noActivity.png" alt="未找到推广活动"></div>`} else {$('#noData').show();}}} else {alert(res.data.msg)}} else {alert(res.data)}$('#list').append(result);isRefreshing = false;},error: function (xhr) {console.log("🚀 ~ refreshItemList ~ xhr:", xhr)isRefreshing = false;},});}

某些浏览器中会出现touchend不触发的问题,解决方式:

在touchcannel中写和touchend一样的方法,当touchend不触发时会执行touchcannel,

  var startY = 0; // 记录触摸开始时的Y坐标document.addEventListener('touchstart', function (e) {startY = e.touches[0].clientY;});document.addEventListener('touchend', function (e) {var endY = e.changedTouches[0].clientY;var atTop = $("#middle").scrollTop() === 0; // 注意使用 scrollTop() 方法来获取滚动距离var distance = endY - startY;if (Math.abs(distance) > 50 && atTop) {if (distance > 0) {$("#list").html('');allDataLoaded = false;refreshItemList(); // 在实际应用中,根据实际情况处理数据加载 }}});document.addEventListener('touchcancel', function (e) {var endY = e.changedTouches[0].clientY;var atTop = $("#middle").scrollTop() === 0; // 注意使用 scrollTop() 方法来获取滚动距离var distance = endY - startY;if (Math.abs(distance) > 50 && atTop) {if (distance > 0) {$("#list").html('');allDataLoaded = false;refreshItemList(); // 在实际应用中,根据实际情况处理数据加载 }}});

7.h5中唤起App,如果安装了App就打开,没安装就下载App

  function openAppOrDownload() {window.addEventListener('visibilitychange', () => {// 监听页面visibilityif (document.hidden) {// 如果页面隐藏了,则表示唤起成功,这时候需要清除下载定时器clearTimeout(timer)}})if (isiOS()) {// iOS设备(因为没安装App的时候唤起不成功,Safari浏览器会报网址无效,所以修改需求不唤起了直接跳转App store下载页面)// timer = setTimeout(() => {//     // 2秒后如果还没打开App,则跳转到App Store下载页面//     window.location.href = iframeConfig.iosStoreLink;// }, 3000)// window.location.href = iframeConfig.iosScheme; // 尝试唤起Apptimer = setTimeout(() => {window.location.href = iframeConfig.iosStoreLink;}, 0)} else if (isAndroid()) {// Android设备var iframe = document.createElement('iframe');iframe.style.display = 'none';iframe.src = iframeConfig.androidScheme;document.body.appendChild(iframe);timer = setTimeout(() => {document.body.removeChild(iframe);// 如果唤起失败,则跳转到下载页面window.location.href = iframeConfig.androidStoreLink;}, 3000)}}

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

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

相关文章

BootStrap框架的使用

一、下载:BootStrap是一套用于 HTML、CSS 和 JS 开发的开源工具集。BootStrap下载官网学习的初级阶段,这里下载生产文件即可将下载的压缩包解压得到包含以下的文件: 记住bootstrap.min.css文件的路径创建html骨架,link引入bootstrap.min.css文件可根据文档中的代码复制到ht…

关于ssh的X11Forwarding功能和vnc端口冲突的问题

前言 偶然间发现有时vnc端口启动不了,显示端口已经启动,但是查看发现默认的59xx端口未启动,但是60xx端口缺被一个sshd进程占用,vnc服务除了默认的59xx端口,还会用到60xx端口。 正是因为这个60xx端口被sshd进程占用,所以vnc才启动不了。 那么这个sshd端口是干嘛的呢,默认…

powerdesigner导出图片PDF

1、导出图片 1.1 CTR+A 选中当前页的设计的表(物理模型或概念模型设计的表都可以)1.2、edit-->exportImage1.3选择自己要保存的图片类型:png/JEPG/SVG等等关于导出来的图片的清晰度,这里要说一下,自己保存的png和jepg都比较模糊,SVG虽然清晰度很高,但是手机上却无法查看…

踩坑记录:windows11下使用 VS2022 和 PCL1.14.1 配置点云开发环境

闲话不多说,具体在windows下下载PCL与解压pcl可以看https://www.yuque.com/huangzhongqing/pcl/这位大佬的文章,那我就具体说一下踩过点坑: 踩坑点1: 按照大佬的文章的步骤进行解压与下载,我的PCL环境下在了K盘中,但是最后不知怎么的我的openni2文件夹下在了C盘里,也就是…

记录--进度条真的是匀速的,不信你看

🧑‍💻 写在开头 点赞 + 收藏 === 学会🤣🤣🤣 引言 众所周知,进度条是程序员大大模拟的程序运行进度,一般会在某些数值卡住不动,引起99%悬案。但是背后的原理你真的清楚吗,其实进度条真的是匀速运动的! 先来看看效果接下来开始实现 创建一个矩形,然后折叠起来,…

excel 二级菜单联动筛选,减少筛选项,缓解打平之后筛选项过多不利于查看的问题

问题 二级菜单联动筛选,让标注更省力 步骤准备一级、二级菜单选项的映射表。公式 -> 根据所选内容创建准备一级下拉菜单选项。数据->数据验证->序列->选中区域准备二级下拉菜单选项。数据->数据验证->序列->公式(=INDIRECT(INDIRECT("C" &…

【Remotery】 Remotery-轻量级的远程实时 CPU/GPU 分析器设计浅析

1.Remotery简介 Remotery是一个轻量级的远程实时CPU/GPU分析器,主要用于监控CPU和GPU上多线程的活动。它提供了一个C文件,可以很容易的集成到项目中,并配置一个实时监控的Web界面,可以通过远程观察和分析程序的性能,适用于监控游戏的实时运行性能和分析移动端应用的性能场…

使用OpenCV进行ROS 2的循线跟踪

原文链接:https://www.youtube.com/watch?v=88y_1ovno8g In this Open Class, well explore how to implement a line-following robot using OpenCV and ROS 2. 在这堂公开课中,我们将探讨如何使用OpenCV和ROS 2来实现一个循线跟踪机器人。You will learn: ✏️ Introduct…

【Kernel】关于Linux内核参数 net.ipv4.ip_local_reserved_ports

网络端口号是如何分配的? 除了给常用服务保留的Well-known Port numbers之外,给客户端的端口号通常是动态分配的,称为ephemeral port(临时端口),在Linux系统上临时端口号的取值范围是通过这个内核参数定义的:net.ipv4.ip_local_port_range (/proc/sys/net/ipv4/ip_local_p…

LLM大模型:推理优化-vLLM显存使用优化

1、众所周知,transformer架构取得了巨大的成功,核心原因之一就是attention的引入。当年那篇论文的名称就叫attention is all you need,可见attention机制在transformer中的巨大作用!attention的计算示意图如下:同一个sequence中,每个token的q会和其他所有token的k求内积,…

sql拦截器的应用

问题:在实际开发当中,日志log的打印无法直接对sql层出现的问题进行整而概之的显示,使得开发中对sql层的具体变动无法直观的查看。当出现sql层方法报错后,需要不断地打log逐条分析错误,再进入sql层分析问题。 解决方案:利于mybatis的sql拦截器工具进行对sql的拦截以及日志…

vite+vue3+ts+pinis搭建项目框架

一:使用 vite 快速创建脚手架 1.创建新项目 命令行输入后,依次选择vue -> typescript。1 yarn create vite vite_vue3_typescript_pinia_template --template2.cd 到项目文件,安装依赖,启动项目1 # 进入项目文件夹 2 cd vite_vue3_typescript_pinia_template 3 # 安装依…