微信浏览器 h5 开发问题总结

微信 h5 项目开发已经告一段落,交付客户使用,总结一下开发过程遇到的问题

ios 设备点击输入框,页面放大

安卓设备目前没发现该问题,页面放大导致在失焦后,页面边缘位置内容显示不全

解决方案:

设置maxium-scale=1.0, user-scalable=no禁止缩放

xml 复制代码
<!doctype html>
<html lang="">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
    />
    <title></title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>
​

ios 设备底部导航

在使用vue-router的push方法跳转页面时候,目标页面默认会生成底部导航条

解决方案:

页面跳转使用replace,全局自定义导航,参考往期文章

下拉刷新操作和页面下拉冲突

微信浏览器中网页默认支持下拉操作,如果页面内部分区域做了下拉刷新。现在当下拉未做下拉刷新的区域,会触发浏览器的下拉动画,之后再去下拉刷新,可能导致下拉刷新不能正确触发

解决方案:

有下拉刷新的页面,非下拉刷新区域禁止下拉操作,例如在页面头部禁止滑动操作

xml 复制代码
<template>
  <div class="layout">
    <div class="layout-header" ref="layoutHeaderRef">
      <div class="flex items-center justify-center h-full">
        <van-icon
          v-if="state.showBack"
          name="arrow-left"
          size="20"
          class="!absolute top-[12px] left-[17px]"
          @click="historyStore.back"
        />
        <div class="text-[17px] font-[700] text-[#000]">{{ state.title }}</div>
      </div>
    </div>
    <div class="layout-content">
      <router-view />
    </div>
  </div>
</template>
​
<script setup>
const layoutHeaderRef = ref(null)
  
onMounted(() => {
  // layoutHeaderRef 禁止滚动事件
  layoutHeaderRef.value.addEventListener('touchmove', (e) => {
    e.preventDefault()
  })
})
</script>
​

van-list @load 事件异常触发

笔者在使用van-pull-refresh和van-list实现了类似微信账单的功能,如果在滚动页面后,点击日期查询数据,预期是走根据日期查询的逻辑,但是这里同时会自动触发van-list的 load 事件,经排查在查询前置空数据,会导致 load 事件异常触发

load 在非预期的情况调用,导致程序异常

解决方案:

根据日期查询时,禁止滚动加载

ini 复制代码
<van-list
  v-model:loading="state.swipeUpLoading"
  @load="onLoad"
  :disabled="state.isListDisabled"
  :finished="state.finished"
  :immediate-check="false"
  finished-text=""
  >
</van-list>
​
function initData() {
 // 禁止滚动加载
 state.isListDisabled = true
 state.list = []
 // 日期查询逻辑
 getRecordList()
}
​
function getRecordList() {
 // 请求完成恢复滚动加载
 state.isListDisabled = false
}
​
​

vant 样式覆盖问题

如果在项目内同时使用van-popup和Toast相关组件,开发环境正常,打包项目运行,碰到Toast相关样式异常问题,查看样式代码发现相关样式被覆盖

解决方案:

main.js入口文件重新引入Toast相关样式

arduino 复制代码
import 'vant/es/toast/style'

https 配置

笔者项目需要调用摄像头,本地调试需要 https 协议,本地代理需要配置 https,这里用 openssl 生成测试证书

解决方案:

本地生成测试证书,openssl下载地址

csharp 复制代码
# 1. 生成私钥(有效期10年)
openssl genrsa -out server.key 2048
​
# 2. 创建证书请求(CSR)
openssl req -new -key server.key -out server.csr -subj "/C=CN/ST=Beijing/L=Beijing/O=YourCompany/CN=yourdomain.com"
​
# 3. 生成自签名证书(有效期365天)
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

vite.config.js配置代理,这样就可以在手机端预览页面使用拍照

javascript 复制代码
export default defineConfig(({ command, mode }) => {
  return {
    server: {
      host: '0.0.0.0',
      cors: true,
      port: envConfig.VITE_PORT,
      https: {
        key: readFileSync('c:/Users/Administrator/key.pem'),
        cert: readFileSync('c:/Users/Administrator/cert.pem'),
      },
      proxy: {
        '/api/api/face': {
          target: envConfig.VITE_API_FACEURL,
          changeOrigin: true,
          rewrite: (path) => path.replace(/^/api/api/face/, '/api/face'),
        },
        '/api': {
          target: envConfig.VITE_API_BASEURL,
          changeOrigin: true,
          rewrite: (path) => path.replace(/^/api/, ''),
        },
      },
    },
  }
}

拍照,裁剪

拍照裁剪可以参考之前文章,这里讲一下拍照后 canvas 绘制图片的问题,在使用drawImage方法绘制图片时候,如果不处理好图片偏移量和宽高,就无法做到图片居中

解决方案:

  1. 通过获取视频和屏幕的宽高比,比较两个比例大小,确定使用宽度还是高度为基准进行缩放
  2. 在使用宽度或者高度进行缩放的时候,另外一边可能比屏幕大或者小,因此需要计算两者差值的一半,将图像居中
javascript 复制代码
// 拍照功能
const takePhoto = () => {
  if (!videoRef.value || !canvasRef.value) return
​
  const video = videoRef.value
  const canvas = canvasRef.value
​
  // 计算适当的缩放比例以保持宽高比
  const videoAspectRatio = video.videoWidth / video.videoHeight
  const screenAspectRatio = window.innerWidth / window.innerHeight
​
  let drawWidth,
    drawHeight,
    offsetX = 0,
    offsetY = 0
​
  if (videoAspectRatio > screenAspectRatio) {
    // 视频更宽,以高度为基准
    drawHeight = window.innerHeight - 44
    drawWidth = drawHeight * videoAspectRatio
    offsetX = (drawWidth - window.innerWidth) / 2
  } else {
    // 视频更高,以宽度为基准
    drawWidth = window.innerWidth
    drawHeight = drawWidth / videoAspectRatio
    offsetY = (drawHeight - window.innerHeight) / 2
  }
​
  // 设置画布尺寸为屏幕尺寸
  canvas.width = window.innerWidth
  canvas.height = window.innerHeight
​
  const ctx = canvas.getContext('2d')
  if (!ctx) return
​
  // 处理前置摄像头的镜像效果
  if (state.isFrontCamera) {
    ctx.translate(canvas.width, 0)
    ctx.scale(-1, 1)
  }
​
  // 绘制时考虑偏移量,确保图像居中
  ctx.drawImage(video, -offsetX, -offsetY, drawWidth, drawHeight)
​
  // 如果是前置摄像头,恢复画布变换
  if (state.isFrontCamera) {
    ctx.setTransform(1, 0, 0, 1, 0, 0)
  }
​
  state.imgUrl = canvas.toDataURL('image/jpeg', 0.8)
  stopCamera()
​
  // 初始化裁剪器
  nextTick(() => {
    if (cropperRef.value) {
      state.cropper = new Cropper(cropperRef.value, {
        viewMode: 0,
        dragMode: 'move',
        aspectRatio: 1,
        modal: true,
        guides: true,
        restore: false,
        cropBoxMovable: false,
        // cropBoxResizable: false,
        // toggleDragModeOnDblclick: false,
        autoCropArea: 1,
        // minContainerWidth: window.innerWidth,
        // minContainerHeight: window.innerHeight,
        ready() {
          state.cropper.setCropBoxData({
            width: 300,
            height: 300,
            left: (this.cropper.containerData.width - 300) / 2,
            top: 145,
          })
        },
      })
    }
  })
}
相关推荐
卸任9 小时前
Vibe coding工具使用心得
前端·ai编程
brien910 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance10 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M10 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写10 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李10 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易11 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马11 小时前
前沿视界
前端
kyriewen11 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
陈随易11 小时前
3000 万人在用的翻译插件,重写一遍就是一门生意
前端·后端·程序员