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

iOS 16.3.1及以下版本Safari中JavaScript代码失效问题求助

部分iPhone Safari浏览器中JavaScript完全失效的问题求助

我的网页JavaScript代码在桌面端、Android设备上运行正常,但在部分iPhone的Safari浏览器中完全失效,输入、点击等交互事件均无法触发。

兼容情况

可正常运行的iPhone机型及版本

  • iPhone 13 Safari 16.6版本
  • iPhone 12 Safari 16.6版本
  • iPhone 13 Safari 16.5.1版本
  • iPhone 11 Safari 16.5版本

无法正常运行的iPhone机型及版本

  • iPhone 11 Safari 16.1版本
  • iPhone 11 Safari 16.3.1版本
  • iPhone XS Max Safari 16.5.1版本
  • iPhone Xr Safari 16.5.1版本
  • iPhone XR Safari 16.3.1版本

代码示例

document.addEventListener("DOMContentLoaded", function() {
    const header = document.querySelector(".header");
    const langSelect = document.querySelector("#lang_select");
    const langList = document.querySelector(".lang_list");

    header.addEventListener("click", function(event) {
      langList.style.display = langList.style.display === "none" ? "block" : "none";
      event.stopPropagation();
    });

    document.addEventListener("click", function(event) {
      if (!langSelect.contains(event.target)) {
        langList.style.display = "none";
      }
    });

    const fieldInputs = document.querySelectorAll(".field input");

fieldInputs.forEach(function(input) {
  input.addEventListener("focus", function() {
    this.parentElement.classList.add("active");
  });

  input.addEventListener("blur", function() {
    if (this.value === "") {
      this.parentElement.classList.remove("active");
    }
  });
});

let isFirstOpen = false;
  const firstBtn = document.querySelector("#firstBtn");
  const firstDrop = document.querySelector("#firstDrop");

  firstBtn.addEventListener("click", function(event) {
    isFirstOpen = !isFirstOpen;

    if (isFirstOpen) {
      firstDrop.style.display = "block";
    } else {
      firstDrop.style.display = "none";
    }

    event.stopPropagation();
  });

  document.addEventListener("click", function(event) {
  if (
    !event.target.closest("#firstBtn") &&
    !event.target.closest("#firstDrop")
  ) {
    const firstDropElement = document.querySelector("#firstDrop");
    if (firstDropElement.style.display !== "none") {
      firstDropElement.style.display = "none";
      isFirstOpen = false;
    }
  }
});

  document.querySelector("#firstInput input").addEventListener("input", function() {
  const inputVal = this.value;
  let num = inputVal.replace(/[^0-9.]+/g, "");
  let regex = /^[+-]?(\d*\.\d+|\d+\.\d*)([eE][+-]?\d+)?$/;

  if (!regex.test(num)) {
    if (num === ".") {
      num = "";
    } else {
      num = num.replace(/(?<=\..*)\./, "");
    }
  }

  this.value = num;

  const firstCryptoCurrencySymbol = document.querySelector("#currency1 a").dataset.cur;
  const secondCryptoCurrencySymbol = document.querySelector("#currency2 a").dataset.cur;

  fetch("/calculateExchangeRate", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      firstCryptoCurrencySymbol: firstCryptoCurrencySymbol,
      secondCryptoCurrencySymbol: secondCryptoCurrencySymbol
    })
  })
  .then(res => res.json())
  .then(data => {
    const exchangeRate = data.rate;
    document.querySelector("#secondInput input").value = num * exchangeRate;
  });
});

document.querySelector("#secondInput input").addEventListener("input", function() {
  const inputVal = this.value;
  let num = inputVal.replace(/[^0-9.]+/g, "");
  let regex = /^[+-]?(\d*\.\d+|\d+\.\d*)([eE][+-]?\d+)?$/;

  if (!regex.test(num)) {
    if (num === ".") {
      num = "";
    } else {
      num = num.replace(/(?<=\..*)\./, "");
    }
  }

  this.value = num;

  const firstCryptoCurrencySymbol = document.querySelector("#currency1 a").dataset.cur;
  const secondCryptoCurrencySymbol = document.querySelector("#currency2 a").dataset.cur;

  fetch("/calculateExchangeRate", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      firstCryptoCurrencySymbol: firstCryptoCurrencySymbol,
      secondCryptoCurrencySymbol: secondCryptoCurrencySymbol
    })
  })
    .then(res => res.json())
    .then(data => {
      const exchangeRate = data.rate;
      document.querySelector("#firstInput input").value = num / exchangeRate;
    });
});

const optionElements = document.querySelectorAll(".option");

optionElements.forEach(function(option) {
  option.addEventListener("click", function(event) {
    if ('ontouchstart' in window || navigator.maxTouchPoints) {
      event.preventDefault();
    }

    let dataCur = this.dataset.cur;
    let imageUrl = this.querySelector(".pm_select_img img").src;
    let optionText = this.querySelector("span").textContent;

    document.querySelector("#firstBtn .pm_select_img img").src = imageUrl;
    document.querySelector("#firstBtn span").textContent = optionText;
    document.querySelector("#firstBtn").dataset.cur = dataCur;

    document.querySelector("#currency1 .pm_select_child").dataset.cur = dataCur;
    document.querySelector("#currency1 .pm_select_child").textContent = dataCur;

    document.querySelector("#hiddenInput").value = dataCur;

    document.querySelector("#amount_send1").dataset.cur = dataCur;
    document.querySelector("#amount_send1 ~ .addons").textContent = dataCur;

    const secondDataCur = document.querySelector("#currency2 a").dataset.cur;

    fetch("/calculateExchangeRate", {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        firstCryptoCurrencySymbol: dataCur,
        secondCryptoCurrencySymbol: secondDataCur
      })
    })
    .then(res => res.json())
    .then(data => {
      const exchangeRate = data.rate;
      document.querySelector(".rate_info").textContent = `1 ${dataCur} = ${exchangeRate} ${secondDataCur}`;
    });

    event.stopPropagation();
  });
});

document.addEventListener("click", function() {
  document.querySelector("#firstDrop").style.display = "none";
});

const optionElementsFirst = document.querySelectorAll(".option1");

optionElementsFirst.forEach(function (option) {
  option.addEventListener("click", function (event) {
    if ("ontouchstart" in window || navigator.maxTouchPoints) {
      event.preventDefault();
    }

    let dataCur = this.dataset.cur;
    let imageUrl = this.querySelector(".pm_select_img img").src;
    let optionText = this.querySelector("span").textContent;

    document.querySelector("#secondBtn .pm_select_img img").src = imageUrl;
    document.querySelector("#secondBtn span").textContent = optionText;
    document.querySelector("#secondBtn").dataset.cur = dataCur;

    document.querySelector("#currency2 .pm_select_child").dataset.cur = dataCur;
    document.querySelector("#currency2 .pm_select_child").textContent = dataCur;

    document.querySelector("#hiddenInput2").value = dataCur;

    document.querySelector("#amount_send2").dataset.cur = dataCur;
    document.querySelector("#amount_send2 ~ .addons").textContent = dataCur;

    const secondDataCur = document.querySelector("#currency1 a").dataset.cur;

    fetch("/calculateExchangeRate", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        firstCryptoCurrencySymbol: dataCur,
        secondCryptoCurrencySymbol: secondDataCur,
      }),
    })
      .then((res) => res.json())
      .then((data) => {
        const exchangeRate = data.rate;
        document.querySelector(".rate_info").textContent = `1 ${dataCur} = ${exchangeRate} ${secondDataCur}`;
      });

    document.querySelector("#secondDrop").style.display = "none";

    event.stopPropagation();
  });
});

document.addEventListener("click", function () {
  document.querySelector("#secondDrop").style.display = "none";
});

let isOpen = false;
const secondBtn = document.querySelector("#secondBtn");
const secondDrop = document.querySelector("#secondDrop");

secondBtn.addEventListener("click", function(event) {
  isOpen = !isOpen;

  if (isOpen) {
    secondDrop.style.display = "block";
  } else {
    secondDrop.style.display = "none";
  }

  event.stopPropagation();
});

document.addEventListener("click", function(event) {
  const secondBtn = document.querySelector("#secondBtn");
  const secondDrop = document.querySelector("#secondDrop");
  const isOpen = secondDrop.style.display !== "none";

  if (
    !event.target.closest("#secondBtn") &&
    !event.target.closest("#secondDrop")
  ) {
    if (isOpen) {
      secondDrop.style.display = "none";
    }
  }
});

})

已尝试的排查步骤

  • 检查代码无语法错误;
  • 改用Bubble重构代码,问题依旧;
  • 添加触摸事件,无改善;
  • Mac模拟器测试正常;
  • BrowserStack模拟器复现问题。

恳请提供解决方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 20:52:02