请求解决Cannot read property 'filter' of undefined筛选错误
嘿,我帮你定位到问题啦!你遇到的Cannot read property 'filter' of undefined错误,核心原因是全局的phones变量从来没有被正确赋值,一直处于undefined状态。
问题拆解:
你在代码开头声明了let phones;,但在parseJSON函数里,你把传入的JSON数据参数也命名为phones——这就导致这个参数覆盖了全局的phones变量,全局的phones始终是空的。当你提交表单触发筛选时,getFilteredPhones函数尝试调用phones.filter(),自然就会抛出错误。
另外还有几个小问题需要修复:
- 你的
createPhone函数是用来创建单个手机卡片的,但你在提交表单时直接把筛选后的数组传给它,没有遍历处理,会导致渲染失败。 - 筛选逻辑里没有处理“All”选项的情况,选择“All”时不会显示所有手机。
createPhone里的$librand和$liyear没有用const声明,会变成全局变量,可能引发意外问题。
修复后的完整代码:
JavaScript 部分
{ let phones; const initValidation = () => { const $form = document.querySelector(`form`); $form.noValidate = true; $form.addEventListener(`submit`, handleSubmitForm); }; const handleSubmitForm = e => { const $form = e.target; e.preventDefault(); if($form.checkValidity()){ const filteredPhones = getFilteredPhones(); // 清空之前的手机列表,避免叠加显示 const $section = document.querySelector(`section`); $section.innerHTML = ''; // 遍历筛选后的数组,创建每个手机卡片 filteredPhones.forEach(phone => createPhone(phone)); } }; const getFilteredPhones = () => { const brand = document.querySelector(`.brands`).value; // 处理“All”选项,返回所有手机 if (brand === "All") { return [...phones]; } return phones.filter(phone => phone.brand === brand); }; const setBrandOptions = brands => { const $select = document.querySelector(`.brands`); brands.sort().forEach(brand => { const $option = document.createElement(`option`); $option.value = brand; $option.textContent = brand; $select.appendChild($option); }); }; const getUniqueBrands = phones => { const uniqueBrands = []; phones.forEach(phone => { if(!uniqueBrands.includes(phone.brand)){ uniqueBrands.push(phone.brand); } }); return uniqueBrands; }; const createPhone = phone => { const $div = document.createElement(`div`); document.querySelector(`section`).appendChild($div); const $img = document.createElement(`img`); $img.setAttribute('src', phone.image); $div.appendChild($img); const $title = document.createElement(`h2`); $title.textContent = phone.name; $div.appendChild($title); const $ul = document.createElement(`ul`); $div.appendChild($ul); // 加上const声明,避免全局变量 const $librand = document.createElement(`li`); $librand.textContent = phone.brand; $ul.appendChild($librand); const $liyear = document.createElement(`li`); $liyear.textContent = phone.year; $ul.appendChild($liyear); }; const parseJSON = (jsonPhones) => { // 把全局的phones赋值为获取到的JSON数据 phones = jsonPhones; phones.forEach(phone => createPhone(phone)); const brands = getUniqueBrands(phones); setBrandOptions(brands); }; const initJSON = () => { const url = "assets/data/phones.json"; fetch(url) .then(r => r.json()) .then(jsonObject => parseJSON(jsonObject)); }; const init = () => { initJSON(); initValidation(); }; init(); }
CSS 部分(保留原代码)
body{ display: flex; flex-direction: column; align-items: center; justify-content: center; } section{ display: flex; flex-direction: row; justify-content: space-around; align-items: flex-end; } div{ display: flex; flex-direction: column; padding-left: 3rem; padding-right: 3rem; } h1{ border-bottom: .1rem solid black; padding-right: 1rem; padding-left: 1rem; margin-bottom: 3rem; } img{ margin-bottom: 1rem; height: 100%; width: 100%; } h2{ font-family: sans-serif; margin-left: 1rem; font-size: 1.3rem; } ul{ margin-left: 1rem; } select{ margin-bottom: 2rem; }
HTML 部分(保留原代码)
<!DOCTYPE html> <html lang="en" dir="ltr"> <head> <meta charset="utf-8"> <title></title> <link rel="stylesheet" href="css/reset.css"> <link rel="stylesheet" href="css/style.css"> </head> <body> <h1>My Phone Collection</h1> <form action=""> <label for="brands">Brand: <select id="brands" class="brands input"> <option value="All">All</option> </select> <span class="error"></span> </label> <button type="submit">Search</button> </form> <section></section> <script type="text/javascript" src="js/script.js"></script> </body> </html>
关键修改点总结:
- 把
parseJSON的参数名改为jsonPhones,并将全局phones赋值为这个参数,确保全局变量有数据。 - 在
handleSubmitForm里先清空section内容,再遍历筛选后的数组创建手机卡片。 - 给
getFilteredPhones添加“All”选项的处理逻辑。 - 给
createPhone里的两个列表项变量加上const声明,避免全局变量泄漏。
这样修改后,你的筛选功能应该就能正常工作啦!
内容的提问来源于stack exchange,提问作者Robbe Verhoest
相关产品推荐
相关产品推荐

