如何通过JavaScript点击事件获取JSON中对应产品的详细信息
基于Fetch实现产品详情点击获取功能
我已经掌握了用Fetch从JSON文件获取数据的基础方法,能展示包含产品图片、名称和「Show Detail」按钮的产品卡片,但不清楚如何通过点击图片或按钮,获取对应产品的id、name、image、url、brand、jenis、deskripsi等详细信息,希望学习对应的Fetch实现方案。
现有JSON数据结构
{ "products": [ { "id": "11", "name": "panda", "brand": "blue", "jenis": "cool panda", "deskripsi": "cute panda", "image": "a8205ca774a533e0053e6fe969443510.jpg", "url": "http://localhost:5000/images/a8205ca774a533e0053e6fe969443510.jpg", "createdAt": "2024-11-28 03:34:22", "updatedAt": "2024-11-29 06:37:36" }, { "id": "13", "name": "fox", "brand": "crowd", "jenis": "fox samurai", "deskripsi": "strongest samurai", "image": "c87dcede772ef2d0fbdd5ceb65237937.jpg", "url": "http://localhost:5000/images/c87dcede772ef2d0fbdd5ceb65237937.jpg", "createdAt": "2024-11-28 14:12:39", "updatedAt": "2024-11-29 06:39:41" }, { "id": "14", "name": "panda", "brand": "digital", "jenis": "samurai", "deskripsi": "its panda samurai", "image": "167748215ed489e0f363d5be562026dd.jpg", "url": "http://localhost:5000/images/167748215ed489e0f363d5be562026dd.jpg", "createdAt": "2024-11-29 03:39:16", "updatedAt": "2024-11-29 06:38:10" } ] }
现有JavaScript代码
const data = "../php/data.json"; const jenisList = document.querySelector('.content'); var urlParams = new URLSearchParams(window.location.search); var jenis = urlParams.get("jenis"); const modalDetail = document.querySelectorAll('.btn-primary'); const getProducts = () => { fetch(data) .then(response => { return response.json(); }).then(responseJson => { if (jenis == null) { showProduct(responseJson.products); } else { jenisProduct(responseJson.products); } }).catch(error => { console.log(error); }); } const showProduct = product => { jenisList.innerHTML = ''; product.forEach(agen => { jenisList.innerHTML += `<div class="product-list"> <div class="flex-div"> <a href="" class="foto-product"><img src="${agen.url}" class="product-img"></a> <div class="product-info"> <p>${agen.name}</p> </div> <a href="#" class="btn-primary" data-toggle="modal" data-target="#movieDetailModal" data-imdbid="${agen.id}">Show Detail</a> </div> </div>` }); } const jenisProduct = product => { jenisList.innerHTML = ''; product.forEach(agen => { if (agen.jenis === jenis) { jenisList.innerHTML += `<div class="product-list"> <div class="flex-div"> <a href="" class="foto-product"><img src="${agen.url}" class="product-img"></a> <div class="product-info"> <p>${agen.name}</p> </div> <a href="${agen.id}" class="btn btn-primary modal-detail-button" data-toggle="modal" data-target="#movieDetailModal" data-imdbid="${agen.id}">Show Detail</a> </div> </div>` } }); } document.addEventListener('DOMContentLoaded', getProducts);
解决方案实现步骤
1. 存储全局产品数据
避免重复请求JSON文件,先把获取到的产品数据存在全局变量中,后续点击时直接从变量中查找:
// 新增全局变量存储所有产品数据 let allProducts = [];
在getProducts函数中更新数据存储:
const getProducts = () => { fetch(data) .then(response => response.json()) .then(responseJson => { // 把产品数据存入全局变量 allProducts = responseJson.products; if (jenis == null) { showProduct(allProducts); } else { jenisProduct(allProducts); } }).catch(error => console.log(error)); }
2. 添加事件委托处理点击
因为产品卡片是动态生成的,不能直接给单个图片/按钮绑定事件,需要给父容器jenisList添加事件委托:
// 新增点击事件委托,处理图片和按钮的点击 jenisList.addEventListener('click', function(e) { e.preventDefault(); // 阻止a标签默认跳转行为 // 判断点击的是图片容器还是详情按钮 let target = e.target; let productId = null; // 点击图片时,找到对应的产品id if (target.classList.contains('product-img')) { productId = target.closest('.product-list').querySelector('.btn-primary').dataset.imdbid; } // 点击详情按钮时,直接获取id else if (target.classList.contains('btn-primary')) { productId = target.dataset.imdbid; } // 如果拿到了产品id,获取详情并展示 if (productId) { getProductDetail(productId); } });
3. 获取并展示产品详情
实现getProductDetail函数,从全局变量中找到对应产品,然后填充到模态框(假设你已经有#movieDetailModal模态框,里面有对应元素展示详情):
const getProductDetail = (productId) => { // 根据id找到对应产品 const product = allProducts.find(item => item.id === productId); if (product) { // 假设模态框内有如下元素,根据实际结构调整 document.querySelector('#modal-product-name').textContent = product.name; document.querySelector('#modal-product-brand').textContent = product.brand; document.querySelector('#modal-product-jenis').textContent = product.jenis; document.querySelector('#modal-product-deskripsi').textContent = product.deskripsi; document.querySelector('#modal-product-image').src = product.url; // 如果用Bootstrap模态框,手动触发显示(可选) $('#movieDetailModal').modal('show'); } }
4. 优化现有生成卡片的代码
统一两个生成卡片函数的按钮和图片标签,避免不一致:
比如在showProduct和jenisProduct中,把图片的a标签href设为#,防止跳转:
<a href="#" class="foto-product"><img src="${agen.url}" class="product-img"></a>
完整修改后的代码
const data = "../php/data.json"; const jenisList = document.querySelector('.content'); var urlParams = new URLSearchParams(window.location.search); var jenis = urlParams.get("jenis"); let allProducts = []; // 全局存储产品数据 const getProducts = () => { fetch(data) .then(response => response.json()) .then(responseJson => { allProducts = responseJson.products; if (jenis == null) { showProduct(allProducts); } else { jenisProduct(allProducts); } }).catch(error => console.log(error)); } const showProduct = product => { jenisList.innerHTML = ''; product.forEach(agen => { jenisList.innerHTML += `<div class="product-list"> <div class="flex-div"> <a href="#" class="foto-product"><img src="${agen.url}" class="product-img"></a> <div class="product-info"> <p>${agen.name}</p> </div> <a href="#" class="btn-primary" data-toggle="modal" data-target="#movieDetailModal" data-imdbid="${agen.id}">Show Detail</a> </div> </div>` }); } const jenisProduct = product => { jenisList.innerHTML = ''; product.forEach(agen => { if (agen.jenis === jenis) { jenisList.innerHTML += `<div class="product-list"> <div class="flex-div"> <a href="#" class="foto-product"><img src="${agen.url}" class="product-img"></a> <div class="product-info"> <p>${agen.name}</p> </div> <a href="#" class="btn btn-primary modal-detail-button" data-toggle="modal" data-target="#movieDetailModal" data-imdbid="${agen.id}">Show Detail</a> </div> </div>` } }); } // 处理产品卡片的点击事件 jenisList.addEventListener('click', function(e) { e.preventDefault(); let productId = null; const target = e.target; // 判断点击的是图片还是按钮 if (target.classList.contains('product-img')) { productId = target.closest('.product-list').querySelector('.btn-primary').dataset.imdbid; } else if (target.classList.contains('btn-primary')) { productId = target.dataset.imdbid; } if (productId) { getProductDetail(productId); } }); // 获取并填充产品详情到模态框 const getProductDetail = (productId) => { const product = allProducts.find(item => item.id === productId); if (product) { // 替换为你模态框中实际的元素选择器 document.querySelector('#modal-product-name').textContent = product.name; document.querySelector('#modal-product-brand').textContent = `品牌:${product.brand}`; document.querySelector('#modal-product-jenis').textContent = `类型:${product.jenis}`; document.querySelector('#modal-product-deskripsi').textContent = `描述:${product.deskripsi}`; document.querySelector('#modal-product-image').src = product.url; // 显示模态框(如果用Bootstrap) $('#movieDetailModal').modal('show'); } } document.addEventListener('DOMContentLoaded', getProducts);
内容的提问来源于stack exchange,提问作者Prima Marianju
相关产品推荐
相关产品推荐

