商品列表及商品详情展示

前言

本文将展示一段结合 HTML、CSS 和 JavaScript 的代码,实现了一个简单的商品展示页面及商品详情,涵盖数据获取、渲染、搜索及排序等功能。

效果展示

点击不同的商品会展示对应的商品详情。

 代码部分

代码总体实现
<!DOCTYPE html>
<html><head><meta charset="utf-8"><meta name="viewport"content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /><title></title><style>* {margin: 0;padding: 0;}#title {width: 100%;height: 50px;background-color: white;font-weight: 800;font-size: 19px;display: flex;justify-content: center;align-items: center;position: fixed;z-index: 1;margin-top: -10px;}#searchContent {width: 95%;margin-left: 2%;height: 4vh;position: relative;}#searchContent input {margin-top: 50px;width: 100%;height: 100%;border-radius: 50px;/* border-style: none; *//* background-color: lightgray; */display: inline-block;}input::placeholder {color: gray;font-size: 16px;text-align: center;}#searchContent img {margin-top: 50px;position: absolute;width: 9%;height: 100%;top: 4px;right: 10px;}#productContent {/* margin-top: 50px; */column-count: 2;column-gap: 10px;padding: 10px;}#product {break-inside: avoid;width: 100%;margin-bottom: 10px;/* background-color: ; */box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);/* padding: 10px; */}#product img {width: 100%;height: auto;}#product div {/* width: 96%; */text-align: center;/* height: 2vh; */margin-left: 2%;margin-top: 0;font-size: 10px;}#name {font-size: 19px;font-weight: 700;}#info {font-weight: 400;/* height: 30px; *//* background-color: blue; */font-size: 15px;width: 100%;display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 2;overflow: hidden;text-overflow: ellipsis;}#product p {margin-left: 2%;margin-bottom: 0;/* color: #666; */color: red;font-size: 20px;}#titles {background-color: orangered;border-radius: 10px;color: yellow;width: 45px;padding: 3px;font-weight: 600;}#orderBut {margin-top: 60px;padding: 5px;}#noResult {text-align: center;font-size: 18px;color: gray;margin-top: 50px;}</style></head><body><div id="title">主页</div><!-- 搜索框部分 --><div id="searchContent"><input id="searchInput" style="text-align: center;font-size: 16px;" type="text" placeholder="搜索框" /><img src="./img/sousuo.png" /></div><div><button id="orderBut">排序</button></div><!-- 内容区域 --><div id="productContent"><!-- 商品部分 --><div id="product"><!-- 商品图片 --><div id="imgBox"><img src="" /></div><!-- 商品名字 --><div id="name"></div><!-- 商品详情 --><div>统一</div><!-- 简介 --><div>方便面</div><!-- 价钱 --><p>¥16.44</p></div></div><script>let data;let productContent = document.getElementById('productContent');let searchInput = document.getElementById('searchInput'); // 获取搜索框输入元素let originalData;// 发起请求获取数据的代码部分保持不变let xhr = new XMLHttpRequest();xhr.open('get', './js/productAbout.json', true);xhr.send();xhr.onreadystatechange = function() {if (xhr.readyState == 4 && xhr.status == 200) {let text = xhr.responseText;data = JSON.parse(text);// 把data数据赋值给originalData,用于输入框清空后显示原始的数据originalData = data;//渲染originalDatarender(originalData);}};function render(data) {let str = "";for (let i in data) {str += `<div id="product"><div id="imgBox" onclick="jumpPage(${i})"><img  src="${data[i].img[0]}" /></div><div id="name">${data[i].name}</div><h3 id="info">${data[i].info}</h3><div id="titles">${data[i].about}</div><p>${data[i].prise}</p></div>`}document.getElementById('productContent').innerHTML = str};// 详情页跳转函数保持不变function jumpPage(index) {localStorage.setItem('details', JSON.stringify(data[index]))window.location.href = './shopAbout.html';}//==========================模糊搜索============================// 先获取输入框元素let input = document.getElementById('searchInput');//给输入框上事件监听 input.addEventListener('input', function() {//用于下面往里面拼东西let str_content = '';//判断输入框里的值let searchValue = input.value.trim()//如果值为空if (searchValue === "") {// 把data数据赋值给originalDataoriginalData = data;} else {//声明originalData为空数组originalData = [];//值不为空的话(说明我往输入框里输入东西了),就循环data数据for (let i in data) {//检查data数组中(namez值info值prise值)是否包括搜索框(searchValue)输入的值if (data[i].name.includes(searchValue) || data[i].info.includes(searchValue) || data[i].prise.includes(searchValue)) {//把data数据的下标i的数据插入到originalData中originalData.push(data[i]);}}}//如果搜索不到if (originalData.length === 0) {// 如果经过筛选后originalData数组为空,说明没有找到符合搜索条件的数据str_content = '<div id="noResult">无符合条件的内容</div>';//否则就是搜索到了} else {// 如果找到了符合条件的数据,就按照原来的逻辑拼接字符串(上面的)for (let i in originalData) {str_content += `<div id="product"><div id="imgBox" onclick="jumpPage(${i})"><img  src="${originalData[i].img[0]}" /></div><div id="name">${originalData[i].name}</div><h3 id="info">${originalData[i].info}</h3><div id="titles">${originalData[i].about}</div><p>${originalData[i].prise}</p></div>`;}}// 获取商品展示区域的元素,假设其id为productContentlet productContent = document.getElementById('productContent');productContent.innerHTML = str_content;});// 	//最后渲染上去// 	render(originalData);// })//========================排序==================//获取按钮let orderBut = document.getElementById('orderBut');//初始化次数为零let num = 0;//给按钮上点击事件orderBut.onclick = function() {//次数+1num++;//如果次数等于1 的时候if (num == 1) {//用sort排序originalData = originalData.sort(function(a, b) {//反值a-b的价钱//如果 a.prise - b.prise 的计算结果小于 0,//即 a 的 prise 值小于 b 的 prise 属性值,此时 a 会排在 b 的前面。return a.prise - b.prise;});console.log(data);//次数等于2的时候//当 b.prise - a.prise 的值小于 0 时,//就是 b 的 prise 属性值小于 a 的 prise 属性值,此时 b 元素会排在 a 元素前面} else if (num == 2) {originalData = originalData.sort(function(a, b) {return b.prise - a.prise;});} else if (num == 3) {num = 0;//展开语法(...),将 data 数组中的元素逐个复制到 originalData 数组中,相当于重置originalData = [...data]}//渲染render(originalData);};</script></body>
</html>

代码详解

HTML
<div id="title">主页</div><!-- 搜索框部分 --><div id="searchContent"><input id="searchInput" style="text-align: center;font-size: 16px;" type="text" placeholder="搜索框" /><img src="./img/sousuo.png" /></div><div><button id="orderBut">排序</button></div><!-- 内容区域 --><div id="productContent"><!-- 商品部分 --><div id="product"><!-- 商品图片 --><div id="imgBox"><img src="" /></div><!-- 商品名字 --><div id="name"></div><!-- 商品详情 --><div>统一</div><!-- 简介 --><div>方便面</div><!-- 价钱 --><p>¥16.44</p></div></div>
CSS
* {margin: 0;padding: 0;}#title {width: 100%;height: 50px;background-color: white;font-weight: 800;font-size: 19px;display: flex;justify-content: center;align-items: center;position: fixed;z-index: 1;margin-top: -10px;}#searchContent {width: 95%;margin-left: 2%;height: 4vh;position: relative;}#searchContent input {margin-top: 50px;width: 100%;height: 100%;border-radius: 50px;/* border-style: none; *//* background-color: lightgray; */display: inline-block;}input::placeholder {color: gray;font-size: 16px;text-align: center;}#searchContent img {margin-top: 50px;position: absolute;width: 9%;height: 100%;top: 4px;right: 10px;}#productContent {/* margin-top: 50px; */column-count: 2;column-gap: 10px;padding: 10px;}#product {break-inside: avoid;width: 100%;margin-bottom: 10px;/* background-color: ; */box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);/* padding: 10px; */}#product img {width: 100%;height: auto;}#product div {/* width: 96%; */text-align: center;/* height: 2vh; */margin-left: 2%;margin-top: 0;font-size: 10px;}#name {font-size: 19px;font-weight: 700;}#info {font-weight: 400;/* height: 30px; *//* background-color: blue; */font-size: 15px;width: 100%;display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 2;overflow: hidden;text-overflow: ellipsis;}#product p {margin-left: 2%;margin-bottom: 0;/* color: #666; */color: red;font-size: 20px;}#titles {background-color: orangered;border-radius: 10px;color: yellow;width: 45px;padding: 3px;font-weight: 600;}#orderBut {margin-top: 60px;padding: 5px;}#noResult {text-align: center;font-size: 18px;color: gray;margin-top: 50px;}
JS
总览
let data;let productContent = document.getElementById('productContent');let searchInput = document.getElementById('searchInput'); // 获取搜索框输入元素let originalData;// 发起请求获取数据的代码部分保持不变let xhr = new XMLHttpRequest();xhr.open('get', './js/productAbout.json', true);xhr.send();xhr.onreadystatechange = function() {if (xhr.readyState == 4 && xhr.status == 200) {let text = xhr.responseText;data = JSON.parse(text);// 把data数据赋值给originalData,用于输入框清空后显示原始的数据originalData = data;//渲染originalDatarender(originalData);}};function render(data) {let str = "";for (let i in data) {str += `<div id="product"><div id="imgBox" onclick="jumpPage(${i})"><img  src="${data[i].img[0]}" /></div><div id="name">${data[i].name}</div><h3 id="info">${data[i].info}</h3><div id="titles">${data[i].about}</div><p>${data[i].prise}</p></div>`}document.getElementById('productContent').innerHTML = str};// 详情页跳转函数保持不变function jumpPage(index) {localStorage.setItem('details', JSON.stringify(data[index]))window.location.href = './shopAbout.html';}//==========================模糊搜索============================// 先获取输入框元素let input = document.getElementById('searchInput');//给输入框上事件监听 input.addEventListener('input', function() {//用于下面往里面拼东西let str_content = '';//判断输入框里的值let searchValue = input.value.trim()//如果值为空if (searchValue === "") {// 把data数据赋值给originalDataoriginalData = data;} else {//声明originalData为空数组originalData = [];//值不为空的话(说明我往输入框里输入东西了),就循环data数据for (let i in data) {//检查data数组中(namez值info值prise值)是否包括搜索框(searchValue)输入的值if (data[i].name.includes(searchValue) || data[i].info.includes(searchValue) || data[i].prise.includes(searchValue)) {//把data数据的下标i的数据插入到originalData中originalData.push(data[i]);}}}//如果搜索不到if (originalData.length === 0) {// 如果经过筛选后originalData数组为空,说明没有找到符合搜索条件的数据str_content = '<div id="noResult">无符合条件的内容</div>';//否则就是搜索到了} else {// 如果找到了符合条件的数据,就按照原来的逻辑拼接字符串(上面的)for (let i in originalData) {str_content += `<div id="product"><div id="imgBox" onclick="jumpPage(${i})"><img  src="${originalData[i].img[0]}" /></div><div id="name">${originalData[i].name}</div><h3 id="info">${originalData[i].info}</h3><div id="titles">${originalData[i].about}</div><p>${originalData[i].prise}</p></div>`;}}// 获取商品展示区域的元素,假设其id为productContentlet productContent = document.getElementById('productContent');productContent.innerHTML = str_content;});// 	//最后渲染上去// 	render(originalData);// })//========================排序==================//获取按钮let orderBut = document.getElementById('orderBut');//初始化次数为零let num = 0;//给按钮上点击事件orderBut.onclick = function() {//次数+1num++;//如果次数等于1 的时候if (num == 1) {//用sort排序originalData = originalData.sort(function(a, b) {//反值a-b的价钱//如果 a.prise - b.prise 的计算结果小于 0,//即 a 的 prise 值小于 b 的 prise 属性值,此时 a 会排在 b 的前面。return a.prise - b.prise;});console.log(data);//次数等于2的时候//当 b.prise - a.prise 的值小于 0 时,//就是 b 的 prise 属性值小于 a 的 prise 属性值,此时 b 元素会排在 a 元素前面} else if (num == 2) {originalData = originalData.sort(function(a, b) {return b.prise - a.prise;});} else if (num == 3) {num = 0;//展开语法(...),将 data 数组中的元素逐个复制到 originalData 数组中,相当于重置originalData = [...data]}//渲染render(originalData);};
JS详解
  • 变量声明
    • data:用于存储从 ./js/productAbout.json 文件获取并解析后的商品数据。
    • productContent:获取页面上商品展示区域的,后续用于更新商品展示内容。
    • searchInput:获取搜索框的 DOM 元素,监听输入事件。
    • originalData:用于存储原始商品数据,在搜索和排序操作中作为基础数据使用。
let data;
let productContent = document.getElementById('productContent');
let searchInput = document.getElementById('searchInput'); 
let originalData;
  • 数据请求
    • 使用 XMLHttpRequest 对象发送 GET 请求到 ./js/productAbout.json 文件。
    • 当请求成功(readyState 为 4 且 status 为 200)时,将响应文本解析为 JSON 格式并赋值给 data
    • 将 data 赋值给 originalData,并调用 render 函数渲染原始数据。
let xhr = new XMLHttpRequest();
xhr.open('get', './js/productAbout.json', true);
xhr.send();
xhr.onreadystatechange = function() {if (xhr.readyState == 4 && xhr.status == 200) {let text = xhr.responseText;data = JSON.parse(text);originalData = data;render(originalData);}
};
  • 数据渲染函数:
    • 该函数用于将商品数据渲染到页面上。
    • 初始化一个空字符串 str,通过 for...in 循环遍历 data 数组。
    • 为每个商品拼接 HTML 字符串,包括商品图片、名称、详情、简介和价格等信息,并为商品图片添加点击事件 jumpPage(${i}),其中 i 为商品在数组中的索引。
    • 最后将拼接好的 HTML 字符串设置为 productContent 的 innerHTML,从而在页面上显示商品。
function render(data) {let str = "";for (let i in data) {str += `<div id="product"><div id="imgBox" onclick="jumpPage(${i})"><img  src="${data[i].img[0]}" /></div><div id="name">${data[i].name}</div><h3 id="info">${data[i].info}</h3><div id="titles">${data[i].about}</div><p>${data[i].prise}</p></div>`}document.getElementById('productContent').innerHTML = str
};
  • 详情页跳转函数:
    • 当用户点击商品图片时,该函数被调用。
    • 它将当前点击商品的数据(data[index])以 JSON 字符串的形式存储在本地存储中,键为 details
    • 然后将页面导航到 ./shopAbout.html,通常这个页面会从本地存储中读取商品详情数据并展示。
function jumpPage(index) {localStorage.setItem('details', JSON.stringify(data[index]))window.location.href = './shopAbout.html';
}
  • 模糊搜索功能:
    • 获取搜索框元素并添加 input 事件监听器,当用户在搜索框中输入内容时触发。
    • 初始化一个空字符串 str_content 用于存储搜索结果的 HTML 内容,获取并修剪搜索框的值 searchValue
    • 如果搜索框为空,将 originalData 重置为原始的 data。否则,清空 originalData 数组,遍历 data 数组,检查商品的名称、详情或价格是否包含搜索值,若包含则将该商品添加到 originalData 中。
    • 如果 originalData 数组为空,说明没有找到符合条件的商品,设置 str_content 为提示信息。否则,遍历 originalData 数组,拼接符合条件的商品的 HTML 内容。
    • 最后更新 productContent 的 innerHTML 以显示搜索结果。
let input = document.getElementById('searchInput');
input.addEventListener('input', function() {let str_content = '';let searchValue = input.value.trim()if (searchValue === "") {originalData = data;} else {originalData = [];for (let i in data) {if (data[i].name.includes(searchValue) || data[i].info.includes(searchValue) || data[i].prise.includes(searchValue)) {originalData.push(data[i]);}}}if (originalData.length === 0) {str_content = '<div id="noResult">无符合条件的内容</div>';} else {for (let i in originalData) {str_content += `<div id="product"><div id="imgBox" onclick="jumpPage(${i})"><img  src="${originalData[i].img[0]}" /></div><div id="name">${originalData[i].name}</div><h3 id="info">${originalData[i].info}</h3><div id="titles">${originalData[i].about}</div><p>${originalData[i].prise}</p></div>`;}}let productContent = document.getElementById('productContent');productContent.innerHTML = str_content;
});
  • 排序功能
    • 获取 “排序” 按钮元素,并初始化一个计数器 num 为 0。
    • 为按钮添加点击事件,每次点击 num 自增 1。
    • 当 num 为 1 时,使用 sort 方法对 originalData 进行升序排序,比较商品价格 prise
    • 当 num 为 2 时,进行降序排序。
    • 当 num 为 3 时,将 num 重置为 0,并通过展开运算符将 data 数组的内容复制给 originalData,恢复原始顺序。
    • 最后调用 render 函数,根据排序后的 originalData 重新渲染商品展示区域。
let orderBut = document.getElementById('orderBut');
let num = 0;
orderBut.onclick = function() {num++;if (num == 1) {originalData = originalData.sort(function(a, b) {return a.prise - b.prise;});} else if (num == 2) {originalData = originalData.sort(function(a, b) {return b.prise - a.prise;});} else if (num == 3) {num = 0;originalData = [...data]}render(originalData);
};

商品详情部分

代码部分

代码总体实现
<!DOCTYPE html>
<html><head><meta charset="utf-8"><meta name="viewport"content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /><title></title><style>* {margin: 0;padding: 0;}.return {width: 100%;/* height: 45px; */background-color: white;font-weight: 800;font-size: 19px;display: flex;/* justify-content: space-between; */align-items: center;position: fixed;z-index: 1;/* margin-top: -10px; */}.return p {/* margin-left: auto; *//* position: absolute; */margin-left: 36%;}.return img {width: 7%;}/* 定义轮播图底板大小 */.banner {width: 100%;/* height: 700px; *//* margin-top: 6vh; *//* margin: auto; *//* border: 5px solid blue; *//* 将多余部分隐藏 */overflow: hidden;font-size: 0;}/* 规定容器里图片规格 */.box img {width: 25%;height: 40vh;/* float: left; *//* display: inline-block; */}/* 包着图片的容器大小 */.box {width: 400%;margin-top: 26px;/* height: 700px; *//* 动画效果运用到每个图片身上 *//* ---名字--持续时间--动画播放次数=无限 */animation: donghua 13s infinite;}/* 当在 @keyframes 创建动画,把它绑定到一个选择器,否则动画不会有任何效果。 */@keyframes donghua {/* 0% 是动画的开始,100% 是动画的完成。 */0% {margin-left: 0;}33.33% {/* 向左移负的1885px。因为上面规定的一张图片的大小是1885px */margin-left: -100%;}66.66% {margin-left: -200%;}100% {margin-left: -300%;}}.priseContent {display: flex;justify-content: space-between;width: 100%;/* height: 60px; */background-color: #ff1e21;}.deja {/* display: inline-block; */}.price {margin-left: 10px;}.priceWord {/* display: inline-block; */background-color: #eb0003;padding: 6px;font-size: 17px;color: white;}.nowPrice {font-size: 25px;color: white;/* margin-left: 10px; */}.infoProduct {width: 96%;margin-left: 2%;margin-top: 5px;}#freeBuy {color: darkgray;}#infoProduct {color: #eb0003;font-weight: 400;}.infoProduct p {color: #eb0003;font-size: 20px;font-weight: 700;}.infoImg img {width: 100%;}.infoImg {/* height: 150vh; */width: 96%;margin-left: 2%;}.line {width: 100%;height: 5px;background-color: lightgray;margin-top: 5px;}.bottonContent {width: 100%;height: 70px;background-color: cadetblue;}/* /底部板子 */.foot-center {width: 100%;display: flex;position: fixed;bottom: 0;z-index: 1;justify-content: space-around;background-color: white;margin-top: 15%;height: 50px;}/* 小块 */.chef {display: flex;flex-direction: column;text-align: center;width: 48px;height: 100%;font-size: 13px;font-weight: 100;margin-bottom: 5px;margin-top: 5px;}.foot-center img {width: 18px;height: 18px;}.kong {width: auto;height: 100px;}.buy {display: flex;align-items: center;justify-content: center;background-color: red;border-radius: 50px;padding-left: 70px;padding-right: 70px;color: white;margin-bottom: 5px;margin-top: 5px;/* margin-left: 50px; */}#wide {height: 10vh;}</style></head><body><!-- 大底板 --><div class="aboutContent"><!-- 返回按键 --><div class="return"><img src="./img/jiantou.png" /><p>详情页</p></div><!-- 轮播图 --><div class="banner"><div class="box"><!-- 图1 --><img src="./img/iwtch.jpg" /><!-- 图2 --><img src="./img/watch3.jpg" /><!-- 图3 --><img src="./img/watch2.jpg" /><!-- 重复图1 --><img src="./img/iwtch.jpg" /></div></div><!-- 价格横条 --><!-- 详情 --><div class="infoProduct"><!-- 名字 --><div id="infoProduct"></div><!-- 详情 --><h3></h3><!-- 包邮 --><div></div><!-- 价格 --><p></p></div><!-- 分割线 --><div class="line"></div><!-- 图片详情 --><div class="infoImg"></div><div id="wide"></div><!-- 底部导航 --><div class="foot"><!-- 底部板子 --><div class="foot-center"><!-- 主页 --><div class="chef"><div class="chef-logo"><img src="./img/home.png" alt="" /></div>主页</div><!-- 分享 --><div class="chef"><div class="chef-logo"><img src="./img/about.png" alt="" /></div>分享</div><!-- 我的 --><div class="chef"><div class="chef-logo"><img src="./img/my.png" alt="" /></div>我的</div><!-- 购买 --><div class="buy"><div class="buy-logo"></div>立即购买</div></div></div></div><script>// 回主页的点击事件let returnHome = document.getElementsByClassName('chef-logo')[0];returnHome.onclick = function() {window.location.href = './shop.html';}// 回主页的点击事件let returnLeft = document.getElementsByClassName('return')[0];returnLeft.onclick = function() {window.location.href = './shop.html';}//通过键名details在详情页获取在主页存的数据//它的作用是将一个 JSON 格式的字符串解析为 JavaScript 对象let data = JSON.parse(localStorage.getItem('details'));console.log(data);//先声明一个空字符串let str = "";//拼接字符串(根据json中的数据拼)//如果想给他改样式 需要在拼接字符串里命名 然后在用名字改样式str += `<div id="aboutContent"><div id="infoProduct">${data.name}</div><h3>${data.info}</h3><div id="freeBuy">${data.about}</div><p>${data.prise}</p>`//获取商品的详情部分,并把拼好的str写进去document.getElementsByClassName('infoProduct')[0].innerHTML = str;//渲染函数(为了渲染图片的)function render() {//=========================轮播图的图片拼接=========================//声明一个空的字符串let imgStr = ""//使用for循环去遍历img数组(json里的)for (let i = 0; i < data.img.length; i++) {// 每次循环都把当前的img下标往imgstr字符串里面拼imgStr += `<img src = "${data.img[i]}"/>	`}// 首张图片在展示时有重复显示的效果imgStr += `<img src = "${data.img[0]}"/>`//获取轮播图的box容器 并把拼好的字符串(imgStr)写进去document.getElementsByClassName('box')[0].innerHTML = imgStr;//=========================详情的图片拼接=========================//声明一个空的字符串let infoImgStr = ""//使用for循环去遍历img数组(json里的)for (let j = 0; j < data.infoImg.length; j++) {// 每次循环都把当前的img下标往infoImgStr字符串里面拼infoImgStr += `<img src = "${data.infoImg[j]}"/>`}//获取详情照片的infoImg容器 并把拼好的字符串(infoImgStr)写进去document.getElementsByClassName('infoImg')[0].innerHTML = infoImgStr;};render();</script></body>
</html>

代码详解

HTML
<!-- 大底板 --><div class="aboutContent"><!-- 返回按键 --><div class="return"><img src="./img/jiantou.png" /><p>详情页</p></div><!-- 轮播图 --><div class="banner"><div class="box"><!-- 图1 --><img src="./img/iwtch.jpg" /><!-- 图2 --><img src="./img/watch3.jpg" /><!-- 图3 --><img src="./img/watch2.jpg" /><!-- 重复图1 --><img src="./img/iwtch.jpg" /></div></div><!-- 价格横条 --><!-- 详情 --><div class="infoProduct"><!-- 名字 --><div id="infoProduct"></div><!-- 详情 --><h3></h3><!-- 包邮 --><div></div><!-- 价格 --><p></p></div><!-- 分割线 --><div class="line"></div><!-- 图片详情 --><div class="infoImg"></div><div id="wide"></div><!-- 底部导航 --><div class="foot"><!-- 底部板子 --><div class="foot-center"><!-- 主页 --><div class="chef"><div class="chef-logo"><img src="./img/home.png" alt="" /></div>主页</div><!-- 分享 --><div class="chef"><div class="chef-logo"><img src="./img/about.png" alt="" /></div>分享</div><!-- 我的 --><div class="chef"><div class="chef-logo"><img src="./img/my.png" alt="" /></div>我的</div><!-- 购买 --><div class="buy"><div class="buy-logo"></div>立即购买</div></div></div></div>
CSS
* {margin: 0;padding: 0;}.return {width: 100%;/* height: 45px; */background-color: white;font-weight: 800;font-size: 19px;display: flex;/* justify-content: space-between; */align-items: center;position: fixed;z-index: 1;/* margin-top: -10px; */}.return p {/* margin-left: auto; *//* position: absolute; */margin-left: 36%;}.return img {width: 7%;}/* 定义轮播图底板大小 */.banner {width: 100%;/* height: 700px; *//* margin-top: 6vh; *//* margin: auto; *//* border: 5px solid blue; *//* 将多余部分隐藏 */overflow: hidden;font-size: 0;}/* 规定容器里图片规格 */.box img {width: 25%;height: 40vh;/* float: left; *//* display: inline-block; */}/* 包着图片的容器大小 */.box {width: 400%;margin-top: 26px;/* height: 700px; *//* 动画效果运用到每个图片身上 *//* ---名字--持续时间--动画播放次数=无限 */animation: donghua 13s infinite;}/* 当在 @keyframes 创建动画,把它绑定到一个选择器,否则动画不会有任何效果。 */@keyframes donghua {/* 0% 是动画的开始,100% 是动画的完成。 */0% {margin-left: 0;}33.33% {/* 向左移负的1885px。因为上面规定的一张图片的大小是1885px */margin-left: -100%;}66.66% {margin-left: -200%;}100% {margin-left: -300%;}}.priseContent {display: flex;justify-content: space-between;width: 100%;/* height: 60px; */background-color: #ff1e21;}.deja {/* display: inline-block; */}.price {margin-left: 10px;}.priceWord {/* display: inline-block; */background-color: #eb0003;padding: 6px;font-size: 17px;color: white;}.nowPrice {font-size: 25px;color: white;/* margin-left: 10px; */}.infoProduct {width: 96%;margin-left: 2%;margin-top: 5px;}#freeBuy {color: darkgray;}#infoProduct {color: #eb0003;font-weight: 400;}.infoProduct p {color: #eb0003;font-size: 20px;font-weight: 700;}.infoImg img {width: 100%;}.infoImg {/* height: 150vh; */width: 96%;margin-left: 2%;}.line {width: 100%;height: 5px;background-color: lightgray;margin-top: 5px;}.bottonContent {width: 100%;height: 70px;background-color: cadetblue;}/* /底部板子 */.foot-center {width: 100%;display: flex;position: fixed;bottom: 0;z-index: 1;justify-content: space-around;background-color: white;margin-top: 15%;height: 50px;}/* 小块 */.chef {display: flex;flex-direction: column;text-align: center;width: 48px;height: 100%;font-size: 13px;font-weight: 100;margin-bottom: 5px;margin-top: 5px;}.foot-center img {width: 18px;height: 18px;}.kong {width: auto;height: 100px;}.buy {display: flex;align-items: center;justify-content: center;background-color: red;border-radius: 50px;padding-left: 70px;padding-right: 70px;color: white;margin-bottom: 5px;margin-top: 5px;/* margin-left: 50px; */}#wide {height: 10vh;}</style></head><body><!DOCTYPE html>
<html><head><meta charset="utf-8"><meta name="viewport"content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /><title></title><style>* {margin: 0;padding: 0;}.return {width: 100%;/* height: 45px; */background-color: white;font-weight: 800;font-size: 19px;display: flex;/* justify-content: space-between; */align-items: center;position: fixed;z-index: 1;/* margin-top: -10px; */}.return p {/* margin-left: auto; *//* position: absolute; */margin-left: 36%;}.return img {width: 7%;}/* 定义轮播图底板大小 */.banner {width: 100%;/* height: 700px; *//* margin-top: 6vh; *//* margin: auto; *//* border: 5px solid blue; *//* 将多余部分隐藏 */overflow: hidden;font-size: 0;}/* 规定容器里图片规格 */.box img {width: 25%;height: 40vh;/* float: left; *//* display: inline-block; */}/* 包着图片的容器大小 */.box {width: 400%;margin-top: 26px;/* height: 700px; *//* 动画效果运用到每个图片身上 *//* ---名字--持续时间--动画播放次数=无限 */animation: donghua 13s infinite;}/* 当在 @keyframes 创建动画,把它绑定到一个选择器,否则动画不会有任何效果。 */@keyframes donghua {/* 0% 是动画的开始,100% 是动画的完成。 */0% {margin-left: 0;}33.33% {/* 向左移负的1885px。因为上面规定的一张图片的大小是1885px */margin-left: -100%;}66.66% {margin-left: -200%;}100% {margin-left: -300%;}}.priseContent {display: flex;justify-content: space-between;width: 100%;/* height: 60px; */background-color: #ff1e21;}.deja {/* display: inline-block; */}.price {margin-left: 10px;}.priceWord {/* display: inline-block; */background-color: #eb0003;padding: 6px;font-size: 17px;color: white;}.nowPrice {font-size: 25px;color: white;/* margin-left: 10px; */}.infoProduct {width: 96%;margin-left: 2%;margin-top: 5px;}#freeBuy {color: darkgray;}#infoProduct {color: #eb0003;font-weight: 400;}.infoProduct p {color: #eb0003;font-size: 20px;font-weight: 700;}.infoImg img {width: 100%;}.infoImg {/* height: 150vh; */width: 96%;margin-left: 2%;}.line {width: 100%;height: 5px;background-color: lightgray;margin-top: 5px;}.bottonContent {width: 100%;height: 70px;background-color: cadetblue;}/* /底部板子 */.foot-center {width: 100%;display: flex;position: fixed;bottom: 0;z-index: 1;justify-content: space-around;background-color: white;margin-top: 15%;height: 50px;}/* 小块 */.chef {display: flex;flex-direction: column;text-align: center;width: 48px;height: 100%;font-size: 13px;font-weight: 100;margin-bottom: 5px;margin-top: 5px;}.foot-center img {width: 18px;height: 18px;}.kong {width: auto;height: 100px;}.buy {display: flex;align-items: center;justify-content: center;background-color: red;border-radius: 50px;padding-left: 70px;padding-right: 70px;color: white;margin-bottom: 5px;margin-top: 5px;/* margin-left: 50px; */}#wide {height: 10vh;}
JS
js详解
  • 返回主页事件
    • 获取元素
      • document.getElementsByClassName('chef-logo')[0] 选择了页面上第一个具有 chef - logo 类名的元素,该元素通常用于代表主页图标。
      • document.getElementsByClassName('return')[0] 选择了页面上第一个具有 return 类名的元素,这个元素可能是返回按钮。
    • 绑定点击事件
      • 对于 returnHome 元素,当点击时,window.location.href = './shop.html'; 会将页面导航到 ./shop.html,实现返回主页的功能。
      • 同样,对于 returnLeft 元素,点击时也会导航到 ./shop.html。这意味着无论是点击主页图标还是返回按钮,都能回到 shop.html 页面。
// 回主页的点击事件
let returnHome = document.getElementsByClassName('chef-logo')[0];
returnHome.onclick = function() {window.location.href = './shop.html';
}
// 回主页的点击事件
let returnLeft = document.getElementsByClassName('return')[0];
returnLeft.onclick = function() {window.location.href = './shop.html';
}
  • 数据渲染部分
    • 获取本地存储数据
      • localStorage.getItem('details') 从本地存储中获取键为 details 的数据,该数据通常是在主页存储的商品详情信息,以 JSON 字符串形式存储。
      • JSON.parse(localStorage.getItem('details')) 将获取到的 JSON 字符串解析为 JavaScript 对象,并赋值给 data 变量。然后通过 console.log(data) 将解析后的数据打印到控制台,方便调试查看。
    • 拼接并渲染商品详情
      • 初始化一个空字符串 str,用于拼接商品详情的 HTML 内容。
      • 根据 data 对象中的属性,将商品的名称(data.name)、详情(data.info)、包邮信息(data.about)和价格(data.prise)拼接成 HTML 片段。
      • document.getElementsByClassName('infoProduct')[0].innerHTML = str; 获取页面上第一个具有 infoProduct 类名的元素,并将拼接好的 HTML 内容设置为该元素的 innerHTML,从而在页面上渲染出商品详情。
//通过键名details在详情页获取在主页存的数据
//它的作用是将一个 JSON 格式的字符串解析为 JavaScript 对象
let data = JSON.parse(localStorage.getItem('details'));
console.log(data);//先声明一个空字符串
let str = "";
//拼接字符串(根据json中的数据拼)
//如果想给他改样式 需要在拼接字符串里命名 然后在用名字改样式
str += `<div id="aboutContent"><div id="infoProduct">${data.name}</div><h3>${data.info}</h3><div id="freeBuy">${data.about}</div><p>${data.prise}</p>
`
//获取商品的详情部分,并把拼好的str写进去
document.getElementsByClassName('infoProduct')[0].innerHTML = str;
  • 轮播图图片渲染
    • 定义 render 函数用于渲染图片。在函数内部,首先初始化一个空字符串 imgStr,用于拼接轮播图的图片 HTML 代码。
    • 通过 for 循环遍历 data.img 数组,data.img 数组应该包含了轮播图所需的图片路径。每次循环将当前图片路径拼接到 imgStr 中。
    • 为了实现轮播图首尾相连的循环效果,在循环结束后,又将第一张图片路径再次拼接到 imgStr 中。
    • document.getElementsByClassName('box')[0].innerHTML = imgStr; 获取页面上第一个具有 box 类名的元素(轮播图容器),并将拼接好的图片 HTML 代码设置为该容器的 innerHTML,从而实现轮播图图片的渲染。
  • 详情图片渲染
    • 同样初始化一个空字符串 infoImgStr,用于拼接商品详情图片的 HTML 代码。
    • 使用 for 循环遍历 data.infoImg 数组,data.infoImg 数组包含商品详情图片的路径。每次循环将当前图片路径拼接到 infoImgStr 中。
    • document.getElementsByClassName('infoImg')[0].innerHTML = infoImgStr; 获取页面上第一个具有 infoImg 类名的元素(商品详情图片容器),并将拼接好的图片 HTML 代码设置为该容器的 innerHTML,完成商品详情图片的渲染。
  • 函数调用:最后调用 render() 函数,执行上述图片渲染操作。
//渲染函数(为了渲染图片的)
function render() {//=========================轮播图的图片拼接=========================//声明一个空的字符串let imgStr = ""//使用for循环去遍历img数组(json里的)for (let i = 0; i < data.img.length; i++) {// 每次循环都把当前的img下标往imgstr字符串里面拼imgStr += `<img src = "${data.img[i]}"/>	`}// 首张图片在展示时有重复显示的效果imgStr += `<img src = "${data.img[0]}"/>`//获取轮播图的box容器 并把拼好的字符串(imgStr)写进去document.getElementsByClassName('box')[0].innerHTML = imgStr;//=========================详情的图片拼接=========================//声明一个空的字符串let infoImgStr = ""//使用for循环去遍历img数组(json里的)for (let j = 0; j < data.infoImg.length; j++) {// 每次循环都把当前的img下标往infoImgStr字符串里面拼infoImgStr += `<img src = "${data.infoImg[j]}"/>`}//获取详情照片的infoImg容器 并把拼好的字符串(infoImgStr)写进去document.getElementsByClassName('infoImg')[0].innerHTML = infoImgStr;
};
render();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/10370.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文阅读:Realistic Noise Synthesis with Diffusion Models

这篇文章是 2025 AAAI 的一篇工作&#xff0c;主要介绍的是用扩散模型实现对真实噪声的仿真模拟 Abstract 深度去噪模型需要大量来自现实世界的训练数据&#xff0c;而获取这些数据颇具挑战性。当前的噪声合成技术难以准确模拟复杂的噪声分布。我们提出一种新颖的逼真噪声合成…

【汽车电子架构】AutoSAR从放弃到入门专栏导读

本文是汽车电子架构&#xff1a;AutoSAR从放弃到入门专栏的导读篇。文章延续专栏文章的一贯作风&#xff0c;从概念与定义入手&#xff0c;希望读者能对AutoSAR架构有一个整体的认识&#xff0c;然后对专栏涉及的文章进行分类与链接。本文首先从AutoSAR汽车软件架构的概念&…

毕业设计--具有车流量检测功能的智能交通灯设计

摘要&#xff1a; 随着21世纪机动车保有量的持续增加&#xff0c;城市交通拥堵已成为一个日益严重的问题。传统的固定绿灯时长方案导致了大量的时间浪费和交通拥堵。为解决这一问题&#xff0c;本文设计了一款智能交通灯系统&#xff0c;利用车流量检测功能和先进的算法实现了…

FPGA|使用quartus II通过AS下载POF固件

1、将开发板设置到AS下载挡位&#xff0c;或者把下载线插入到AS端口 2、打开quartus II&#xff0c;选择Tools→Programmer→ Mode选择Active Serial Programming 3、点击左侧Add file…&#xff0c;选择 .pof 文件 →start 4、勾选program和verify&#xff08;可选&#xff0…

适合超多氛围灯节点应用的新选择

文章目录 1.前言2.芯片简介2.1 高动态RGB照明2.2 灵活的通信模式2.3 精确的颜色控制2.4 高性能与可靠性2.5 易于集成与控制 3.硬件介绍3.1 方案框图3.2 通信模式3.3 器件选型 4.基础操作4.1 基础操作示例4.2 状态机4.3 启动行为4.4 诊断 5 颜色控制和温度稳定化5.1 颜色控制5.2…

MATLAB-Simulink并行仿真示例

一、概述 在进行simulink仿真的过程中常常遇到CPU利用率较低&#xff0c;仿真缓慢的情况&#xff0c;可以借助并行仿真改善这些问题&#xff0c;其核心思想是将参数扫描、蒙特卡洛分析或多工况验证等任务拆分成多个子任务&#xff0c;利用多核CPU或计算集群的并行计算能力&…

运算符重载(输出运算符<<) c++

我们来看下面这个Bug 报错1&#xff1a;打印整形&#xff08;int&#xff09;可以直接打印&#xff0c;打印字符&#xff08;char&#xff09;也可以直接打印&#xff0c;那是因为本身就已经给我们的内置类型准备好了一个输出运算符&#xff0c;可以直接用&#xff0c;但是我们…

【C++】类和对象(5)

目录 一、构造函数补充1、初始化列表 二、类型转换三、static成员四、友元1、友元函数2、友元类 五、内部类六、匿名对象 一、构造函数补充 对于之前讲解的构造函数&#xff0c;还有一些更深层次的内容要进行补充&#xff0c;接下来进行补充内容的讲解。 1、初始化列表 在我…

反向代理模块b

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当于…

Python - Quantstats量化投资策略绩效统计包 - 详解

使用Quantstats包做量化投资绩效统计的时候因为Pandas、Quantstats版本不匹配踩了一些坑&#xff1b;另外&#xff0c;Quantstats中的绩效统计指标非常全面&#xff0c;因此详细记录一下BUG修复方法、使用说明以及部分指标的内涵示意。 一、Quantstats安装及版本匹配问题 可以…

C#,入门教程(13)——字符(char)及字符串(string)的基础知识

上一篇&#xff1a; C#&#xff0c;入门教程(12)——数组及数组使用的基础知识https://blog.csdn.net/beijinghorn/article/details/123918227 字符串的使用与操作是必需掌握得滚瓜烂熟的编程技能之一&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; C#语言实…

主流的AEB标准有哪些?

目录 1、AEB的技术构成与工作原理 2、典型应用场景举例 3、AEB的功能分类 4、AEB系统性能评估的关键因素 5、全球AEB技术标准概览 5.1、联合国欧洲经济委员会&#xff08;UN ECE&#xff09; 5.2、美国NHTSA法规 5.3、中国标准 5.4、印度AIS 185 5.5、澳大利亚ADR法规…

Linux网络 | 网络层IP报文解析、认识网段划分与IP地址

前言&#xff1a;本节内容为网络层。 主要讲解IP协议报文字段以及分离有效载荷。 另外&#xff0c; 本节也会带领友友认识一下IP地址的划分。 那么现在废话不多说&#xff0c; 开始我们的学习吧&#xff01;&#xff01; ps&#xff1a;本节正式进入网络层喽&#xff0c; 友友们…

基于Python的药物相互作用预测模型AI构建与优化(上.文字部分)

一、引言 1.1 研究背景与意义 在临床用药过程中,药物相互作用(Drug - Drug Interaction, DDI)是一个不可忽视的重要问题。当患者同时服用两种或两种以上药物时,药物之间可能会发生相互作用,从而改变药物的疗效、增加不良反应的发生风险,甚至危及患者的生命安全。例如,…

TCL C++开发面试题及参考答案

进程和线程的区别 进程和线程都是操作系统中重要的概念,它们在很多方面存在着明显的区别。 从概念上来说,进程是资源分配的基本单位,每个进程都有自己独立的地址空间、内存、文件描述符等资源。例如,当我们在计算机上同时运行多个应用程序,像浏览器、文本编辑器等,每个应…

如何获取当前的位置信息

文章目录 1 概念介绍2 使用方法3 示例代码3 体验分享 我们在上一章回中介绍了如何实现滑动菜单相关的内容&#xff0c;本章回中将介绍如何获取位置信息.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1 概念介绍 我们在这里说的获取位置信息本质上是获取当前手机所在位置的…

python-leetcode-旋转链表

61. 旋转链表 - 力扣&#xff08;LeetCode&#xff09; # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val val # self.next next class Solution:def rotateRight(self, head: Optional[ListN…

基于排队理论的物联网发布/订阅通信系统建模与优化

论文标题 英文标题&#xff1a;Queuing Theory-Based Modeling and Optimization of a Publish/Subscribe IoT Communication System 中文标题&#xff1a;基于排队理论的物联网发布/订阅通信系统建模与优化 作者信息 Franc Pouhela Anthony Kiggundu Hans D. Schotten …

[EAI-026] DeepSeek-VL2 技术报告解读

Paper Card 论文标题&#xff1a;DeepSeek-VL2: Mixture-of-Experts Vision-Language Models for Advanced Multimodal Understanding 论文作者&#xff1a;Zhiyu Wu, Xiaokang Chen, Zizheng Pan, Xingchao Liu, Wen Liu, Damai Dai, Huazuo Gao, Yiyang Ma, Chengyue Wu, Bin…

基于Python的药物相互作用预测模型AI构建与优化(下.代码部分)

四、特征工程 4.1 分子描述符计算 分子描述符作为量化分子性质的关键数值,能够从多维度反映药物分子的结构和化学特征,在药物相互作用预测中起着举足轻重的作用。RDKit 库凭借其强大的功能,为我们提供了丰富的分子描述符计算方法,涵盖了多个重要方面的分子性质。 分子量…