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

Uncaught TypeError错误排查:无法读取null的addEventListener属性

错误原因排查与解决办法

直接触发Uncaught TypeError的原因

你的JS代码存在语法错误:$(document).ready的回调函数内部多了一个多余的闭合大括号},导致后续获取purchaseAmount元素、绑定事件的代码脱离了DOM就绪回调的范围,在页面DOM未完全加载完成时就执行了。此时#purchaseAmount元素还未被渲染,document.querySelector('#purchaseAmount')返回null,调用addEventListener自然会触发"Cannot read properties of null"错误。

其他影响功能的代码问题及修复

除了上述语法错误,还有多处问题导致运费计算功能无法正常运行:

  • 提交按钮是<a>标签而非<button>,JS中$("button").on('click', ...)无法匹配到元素,点击提交不会触发计算逻辑。
  • valAsNumber未用let/var声明,会成为全局变量,存在作用域污染风险。
  • shippingCost是在点击事件回调内部声明的局部变量,外部代码无法访问,会导致formatter.format(shippingCost)报错。
  • HTML中缺少id="finalQuote"的元素,无法显示计算出的运费结果。
  • 单选按钮的id重复(如两个preferredCustomer),违反HTML规范,会导致标签与输入框的关联异常。
  • 提交按钮绑定了onclick="AddQuote()",但JS中未定义该函数,会触发额外错误。

修复后的完整代码

修复后的JavaScript代码

$(document).ready(function() {
    let fnum = 0,
        snum = 0,
        valAsNumber = 0; // 提前声明变量,避免全局污染

    // 监听Preferred Customer单选按钮变化
    $('input[name="fnum"]').on("click", function() {
        fnum = parseFloat($('input[name="fnum"]:checked').val());
    });

    // 监听Trusted Traveler单选按钮变化
    $('input[name="snum"]').on("click", function() {
        snum = parseFloat($('input[name="snum"]:checked').val());
    });

    // 监听购买金额输入变化
    let purchaseAmount = document.querySelector('#purchaseAmount');
    purchaseAmount.addEventListener('input', function() {
        // 处理空值或非数字输入,默认设为0
        valAsNumber = parseFloat(purchaseAmount.value) || 0;
    });

    // 绑定提交按钮点击事件(匹配a标签的id)
    $("#btnSubmit").on('click', function(e) {
        e.preventDefault(); // 阻止a标签默认跳转行为
        var boundaryValue1 = 24.99;
        var boundaryValue2 = 49.99;
        var shippingSubCost = 0;

        // 根据购买金额计算基础运费
        if (valAsNumber <= boundaryValue1) {
            shippingSubCost = 5.00;
        } else if (valAsNumber > boundaryValue1 && valAsNumber <= boundaryValue2) {
            shippingSubCost = 2.50;
        } else {
            shippingSubCost = 0.00;
        }

        // 计算最终运费
        var shippingCost = (shippingSubCost * fnum) + (valAsNumber * snum);
        const formatter = new Intl.NumberFormat('en-US', {
            style: 'currency',
            currency: 'USD',
        });

        var outputShippingCost = formatter.format(shippingCost);

        // 打印调试信息
        console.log("Shipping Cost = " + outputShippingCost);
        console.log("Purchase Amount = $" + valAsNumber.toFixed(2));
        console.log("shippingSubFee = $" + shippingSubCost.toFixed(2));
        console.log("preferredCustomer multiplier = " + fnum);
        console.log("trustedTraveler multiplier = " + snum);

        // 将结果显示到页面
        $("#finalQuote").val(outputShippingCost);
    });
});

修复后的HTML代码

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
  <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
    <a class="navbar-brand" href="index.html">Get your Shipping Quote Now!</a>
    <div class="collapse navbar-collapse" id="navbarsExampleDefault">
      <ul class="navbar-nav mr-auto">
        <li class="nav-item">
          <a class="nav-link" href="index.html">Home</a>
        </li>
      </ul>
    </div>
  </nav>

  <main role="main" class="container" style="padding-top: 5em">
    <h1 style="text-align: center;">Enter Information</h1>

    <form id="addForm" name="addForm">
      <div class="form-group">
        <div class="card">
          <div class="card-header">
            <b>Customer Information</b>
          </div>
          <div style="padding: 10px">
            <div class="form-group">
              <label for="firstName">First Name</label>
              <input type="text" class="form-control" id="firstName" name="firstName">
            </div>
            <div class="form-group">
              <label for="lastName">Last Name</label>
              <input type="text" class="form-control" id="lastName" name="lastName">
            </div>
            <div class="form-group">
              <label for="address">Address</label>
              <input type="text" class="form-control" id="address" name="address">
            </div>
            <div class="form-row">
              <div class="form-group col-md-6">
                <label for="city">City</label>
                <input type="text" class="form-control" id="city" name="city">
              </div>
              <div class="form-group col-md-4">
                <label for="province">Province</label>
                <select id="province" class="form-control" name="province">
                  <option value="ON" selected>ON</option>
                  <option value="NL">NL</option>
                  <option value="PE">PE</option>
                  <option value="NS">NS</option>
                  <option value="NB">NB</option>
                  <option value="QC">QC</option>
                  <option value="MB">MB</option>
                  <option value="SK">SK</option>
                  <option value="AB">AB</option>
                  <option value="BC">BC</option>
                  <option value="YT">YT</option>
                  <option value="NT">NT</option>
                  <option value="NU">NU</option>
                </select>
              </div>
              <div class="form-group col-md-2">
                <label for="postalCode">Postal Code</label>
                <input type="text" class="form-control" id="postalCode" name="postalCode">
              </div>
            </div>
            <div class="form-row">
              <div class="form-group col-md-4">
                <label for="phone">Phone Number</label>
                <input type="text" class="form-control" id="phone" name="phone">
              </div>
              <div class="form-group col-md-8">
                <label for="email">Email address</label>
                <input type="email" class="form-control" id="email" name="email">
              </div>
            </div>
          </div>
        </div>
        <br>
        <div class="card">
          <div class="card-header">
            <b>Customer Purchasing Information</b>
          </div>
          <div class="card-body">
            <div id="optionfood">
              <div class="form-group">
                <label>Are you a Preferred Customer?</label>
                <input type="radio" id="preferredCustomerYes" name="fnum" value="0">Yes
                <input type="radio" id="preferredCustomerNo" name="fnum" value="1" checked>No
                <br>
              </div>
              <div class="form-group">
                <label>Are you a Trusted Traveler?</label>
                <input type="radio" id="trustedTravelerYes" name="snum" value="0" checked>Yes
                <input type="radio" id="trustedTravelerNo" name="snum" value="0.15">No
                <br>
              </div>
              <div class="form-group">
                <label for="purchaseAmount">Purchase Amount ($CDN)</label>
                <input type="number" class="form-control" name="purchaseAmount" id="purchaseAmount" step="0.01" value="" placeholder="$0.00" min="0.01">
              </div>
              <!-- 添加显示运费的输入框 -->
              <div class="form-group">
                <label for="finalQuote">Calculated Shipping Cost (USD)</label>
                <input type="text" class="form-control" id="finalQuote" readonly>
              </div>
            </div>
          </div>
        </div>
      </div>
      <a type="button" class="btn btn-primary" id="btnSubmit" style="color: white">Submit</a>
    </form>
  </main>
</body>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:03:07