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

Firebase+Cookie购物车添加功能报错:Cannot read properties of null(quantity)

问题排查与修复方案

核心错误原因

控制台抛出的Cannot read properties of null (reading 'quantity')错误,根源在于以下几处代码逻辑问题:

  • addCart函数中未定义products变量:尝试复制products但该变量从未声明,导致productsCopy为空数组,filter后返回undefined,给quantity赋值时触发空值读取错误。
  • addCartToHTML函数遍历对象错误:遍历了Firebase中的所有商品,而非购物车中已添加的商品,并且错误访问商品本身的quantity属性(商品数据里没有这个字段,购物车项才会存储)。
  • changeQuantity函数缺少空值判断:当购物车项被删除后,直接访问listCart[$idProduct].quantity会触发空值错误。

具体修复步骤

1. 修复addCart函数

从Firebase快照中直接获取商品数据并筛选目标商品,不再依赖未定义的变量:

function addCart($idProduct){
    firebase.database().ref('Products/').once('value').then(function(snapshot){
        const products = snapshot.val();
        // 如果该商品不在购物车中
        if(!listCart[$idProduct]) 
        {
            // 从Firebase数据中筛选目标商品
            const targetProduct = Object.values(products).filter(item => item.pid == $idProduct)[0];
            if(targetProduct){
                listCart[$idProduct] = {...targetProduct, quantity: 1};
            }
        }else{
            // 如果该商品已在购物车中,仅增加数量
            listCart[$idProduct].quantity++;
        }
        document.cookie = "listCart=" + JSON.stringify(listCart) + "; expires=Thu, 31 Dec 2025 23:59:59 UTC; path=/;";
        addCartToHTML();
    });
}

2. 重构addCartToHTML函数

只遍历购物车中的商品,正确读取购物车项的quantity属性:

function addCartToHTML(){
    firebase.database().ref('Products/').once('value').then(function(snapshot){
        const listCartHTML = document.querySelector('.listCart');
        listCartHTML.innerHTML = '';
        const products = snapshot.val();
        const totalHTML = document.querySelector('.totalQuantity');
        let totalQuantity = 0;

        // 遍历购物车中的商品
        for(const [pid, cartItem] of Object.entries(listCart)){
            if(cartItem){
                const product = Object.values(products).find(item => item.pid == pid);
                if(product){
                    const newCart = document.createElement('div');
                    newCart.classList.add('item');
                    newCart.innerHTML = 
                    `<img src="${product.image}">
                    <div class="content">
                        <div class="name">${product.pname}</div>
                        <div class="price">$${product.price} / 1件商品</div>
                    </div>
                    <div class="quantity">
                        <button onclick="changeQuantity(${pid}, '-')">-</button>
                        <span class="value">${cartItem.quantity}</span>
                        <button onclick="changeQuantity(${pid}, '+')">+</button>
                    </div>`;
                    listCartHTML.appendChild(newCart);
                    totalQuantity += cartItem.quantity;
                }
            }
        }
        totalHTML.innerText = totalQuantity;
    });
}

3. 修复changeQuantity函数

增加空值判断,避免访问不存在的购物车项:

function changeQuantity($idProduct, $type){
    // 先判断购物车项是否存在
    if(!listCart[$idProduct]) return;
    
    switch ($type) {
        case '+':
            listCart[$idProduct].quantity++;
            break;
        case '-':
            listCart[$idProduct].quantity--;
            // 如果数量<=0则从购物车中移除商品
            if(listCart[$idProduct].quantity <= 0){
                delete listCart[$idProduct];
            }
            break;
        default:
            break;
    }
    document.cookie = "listCart=" + JSON.stringify(listCart) + "; expires=Thu, 31 Dec 2025 23:59:59 UTC; path=/;";
    addCartToHTML();
}

完整修正后的index.js代码

firebase.initializeApp(config2);
window.onload=function(){
    this.addDataToHTML();
}

let iconCart = document.querySelector('.iconCart');
let cart = document.querySelector('.cart');
let container = document.querySelector('.container');
let close = document.querySelector('.close');

iconCart.addEventListener('click', function(){
    if(cart.style.right === '-100%'){
        cart.style.right = '0';
        container.style.transform = 'translateX(-400px)';
    }else{
        cart.style.right = '-100%';
        container.style.transform = 'translateX(0)';
    }
})
close.addEventListener('click', function (){
    cart.style.right = '-100%';
    container.style.transform = 'translateX(0)';
})

// 在列表中显示产品数据
function addDataToHTML(){
    firebase.database().ref('Products/').once('value').then(function(snapshot){
        let listProductHTML = document.querySelector('.listProduct');
        listProductHTML.innerHTML = '';
        const data = snapshot.val();
        if(data != null){
            for(const [key,value] of Object.entries(data)){
                let newProduct = document.createElement('div');
                newProduct.classList.add('item');
                newProduct.innerHTML = 
                `<img src="${value.image}" alt="">
                <h2>${value.pname}</h2>
                <div class="price">$${value.price}</div>
                <button onclick="addCart(${value.pid})">加入购物车</button>`;
                listProductHTML.appendChild(newProduct);
            }
        }
    });
}

let listCart = {}; // 改为对象更适合按pid存储
function checkCart(){
    const cookieValue = document.cookie
    .split('; ')
    .find(row => row.startsWith('listCart='));
    if(cookieValue){
        listCart = JSON.parse(cookieValue.split('=')[1]);
    }else{
        listCart = {};
    }
}
checkCart();

function addCart($idProduct){
    firebase.database().ref('Products/').once('value').then(function(snapshot){
        const products = snapshot.val();
        if(!listCart[$idProduct]){
            const targetProduct = Object.values(products).filter(item => item.pid == $idProduct)[0];
            if(targetProduct){
                listCart[$idProduct] = {...targetProduct, quantity: 1};
            }
        }else{
            listCart[$idProduct].quantity++;
        }
        document.cookie = "listCart=" + JSON.stringify(listCart) + "; expires=Thu, 31 Dec 2025 23:59:59 UTC; path=/;";
        addCartToHTML();
    });
}

addCartToHTML();
function addCartToHTML(){
    firebase.database().ref('Products/').once('value').then(function(snapshot){
        const listCartHTML = document.querySelector('.listCart');
        listCartHTML.innerHTML = '';
        const products = snapshot.val();
        const totalHTML = document.querySelector('.totalQuantity');
        let totalQuantity = 0;

        for(const [pid, cartItem] of Object.entries(listCart)){
            if(cartItem){
                const product = Object.values(products).find(item => item.pid == pid);
                if(product){
                    const newCart = document.createElement('div');
                    newCart.classList.add('item');
                    newCart.innerHTML = 
                    `<img src="${product.image}">
                    <div class="content">
                        <div class="name">${product.pname}</div>
                        <div class="price">$${product.price} / 1件商品</div>
                    </div>
                    <div class="quantity">
                        <button onclick="changeQuantity(${pid}, '-')">-</button>
                        <span class="value">${cartItem.quantity}</span>
                        <button onclick="changeQuantity(${pid}, '+')">+</button>
                    </div>`;
                    listCartHTML.appendChild(newCart);
                    totalQuantity += cartItem.quantity;
                }
            }
        }
        totalHTML.innerText = totalQuantity;
    });
}

function changeQuantity($idProduct, $type){
    if(!listCart[$idProduct]) return;
    
    switch ($type) {
        case '+':
            listCart[$idProduct].quantity++;
            break;
        case '-':
            listCart[$idProduct].quantity--;
            if(listCart[$idProduct].quantity <= 0){
                delete listCart[$idProduct];
            }
            break;
        default:
            break;
    }
    document.cookie = "listCart=" + JSON.stringify(listCart) + "; expires=Thu, 31 Dec 2025 23:59:59 UTC; path=/;";
    addCartToHTML();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 22:37:35