You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+TypeScript视频网站问题求助:页面刷新与iOS兼容性

问题1:刷新模板页时state丢失导致异常的解决方案

核心原因

useLocation().state仅存在于内存路由导航过程中,页面刷新后浏览器会重新加载页面,state数据会被清空,直接解构location.state会抛出类型错误,进而引发页面异常。

修复步骤

  1. 添加状态检查与重定向:在组件中先判断state是否存在,不存在则立即重定向到首页,并用replace: true避免错误页面留在历史栈。
  2. 安全解构state数据:使用可选链操作符避免空值解构报错,同时设置默认值保证组件正常渲染。
  3. 修正DOM副作用位置:将操作document.body.style.overflow的代码移至useEffect,避免组件重复渲染时多次执行。
  4. 修复未定义变量:补充代码中缺失的selectedVideoIndex状态定义。

修改后的代码片段

import React, { useState, useEffect } from 'react';
import './Grille_video_style.css';
import { useLocation, useNavigate } from 'react-router-dom';
import styled from '@emotion/styled';

//Adaptable web/phone style
const ContainerStyle = styled.div`
  top: 0;
  left: 0;
  position: fixed;
  width: 100%;
  height: 100vh;
  justify-content: center;
  background-color: black;
  
  //Adaptation for phone
  @media (max-width: 85em) {
    width: 70%;
  }
`;


const Grille_video: React.FC = () => {
  const location = useLocation();
  const navigate = useNavigate();
  // 补充未定义的选中视频索引状态
  const [selectedVideoIndex, setSelectedVideoIndex] = useState(0);
  const [isMobile, setIsMobile] = useState<boolean>(window.matchMedia('(max-width: 85em)').matches);

  // 检查state是否存在,不存在则重定向到首页
  useEffect(() => {
    if (!location.state?.paths) {
      navigate('/Grille', { replace: true });
    }
  }, [location.state, navigate]);

  // 安全获取视频路径数据,避免空值报错
  const paths = location.state?.paths || [];
  const [videos, setVideos] = useState(paths);

  // 处理页面滚动禁用与组件卸载时的恢复
  useEffect(() => {
    document.body.style.overflow = 'hidden';
    return () => {
      document.body.style.overflow = 'auto';
    };
  }, []);

  // 返回按钮点击事件
  const handleBackClick = () => {
    document.exitFullscreen().catch(err => console.log(err));
    navigate('/Grille');
  };

  // 监听窗口大小变化,判断是否为移动端
  useEffect(() => {
    const handleResize = () => {
      setIsMobile(window.matchMedia('(max-width: 85em)').matches);
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return (
    <ContainerStyle>
      <button onClick={handleBackClick} style={styles.backButton}>
        Retour
      </button>
      {videos.map((src, index) => (
        <video
          key={index}
          style={styles.videoMain}
          controls={isMobile ? selectedVideoIndex === index : true}
          autoPlay
          loop
          muted
          className="custom-video"
          preload="auto"
        >
          <source src={src} type="video/mp4" />
          Your browser does not support the video tag.
        </video>
      ))}
    </ContainerStyle>
  );
};

const styles: { [key: string]: React.CSSProperties | any } = {
  backButton: {
    position: 'absolute',
    top: '10px',
    left: '10px',
    padding: '10px 20px',
    backgroundColor: '#EA6666',
    color: 'white',
    border: 'none',
    borderRadius: '8px',
    cursor: 'pointer',
    zIndex: 1100,
  },
  videoMain: {
    position: 'absolute',
    width: '100vw', 
    height: 'calc(100vh - 50px)',
    objectFit: 'cover',
    opacity: 1,
    zIndex: 1000,
  },
};

export default Grille_video;

问题2:iPhone设备兼容解决方案

核心思路

iOS Safari存在大量与安卓浏览器的特性差异,需从CSS前缀、视频行为、触摸事件、viewport配置等维度针对性适配,优先使用特性检测而非设备型号检测。

具体适配方案

  1. 基础viewport配置
    确保HTML头部的viewport标签包含viewport-fit=cover,解决刘海屏、灵动岛的布局适配问题:

    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
    
  2. CSS属性兼容

    • 对object-fit等属性添加-webkit前缀,兼容旧版iOS Safari:
      .custom-video {
        object-fit: cover;
        -webkit-object-fit: cover;
      }
      
    • 解决iOS滚动时fixed定位元素抖动问题:
      body {
        -webkit-overflow-scrolling: touch;
      }
      
    • 优化字体渲染效果:
      * {
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
      }
      
  3. 视频播放行为适配

    • iOS Safari对autoPlay有严格限制,需同时设置muted和playsinline(避免自动全屏):
      <video
        ...
        playsinline
        muted
        autoPlay
      >
      
    • 若需统一跨设备控制栏样式,建议实现自定义视频控制组件,避免依赖原生控件差异。
  4. 触摸与交互适配

    • 解决iOS点击300ms延迟问题:
      button, .custom-video {
        touch-action: manipulation;
      }
      
    • 优先使用pointerdown/pointerup事件替代touch/click,实现跨设备交互统一。
  5. 调试与问题定位

    • 使用Safari开发者工具连接iPhone设备,实时查看控制台错误、DOM结构与样式计算结果。
    • 针对特定场景,可临时通过navigator.userAgent检测iOS环境做兼容(仅作为最后手段):
      const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
      

参考资源

  • Safari官方WebKit兼容性文档,查询iOS Safari支持的Web特性
  • MDN浏览器兼容性表格,检索CSS/JS API的设备支持情况
  • caniuse,查询前端特性的跨设备支持数据
  • 苹果开发者网站的Web开发指南,获取iOS适配最佳实践

内容的提问来源于stack exchange,提问作者PierreCode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:04:56