商品列表及商品详情展示

前言

本文将展示一段结合 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.mzph.cn/web/67863.shtml

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

相关文章

大模型综述一镜到底(全文八万字) ——《Large Language Models: A Survey》

论文链接&#xff1a;https://arxiv.org/abs/2402.06196 摘要&#xff1a;自2022年11月ChatGPT发布以来&#xff0c;大语言模型&#xff08;LLMs&#xff09;因其在广泛的自然语言任务上的强大性能而备受关注。正如缩放定律所预测的那样&#xff0c;大语言模型通过在大量文本数…

【C++】B2124 判断字符串是否为回文

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述输入格式&#xff1a;输出格式&#xff1a;样例&#xff1a; &#x1f4af;方法一&#xff1a;我的第一种做法思路代码实现解析 &#x1f4af;方法二&#xff1a;我…

ubuntuCUDA安装

系列文章目录 移动硬盘制作Ubuntu系统盘 前言 根据前篇“移动硬盘制作Ubuntu系统盘”安装系统后&#xff0c;还不能够使用显卡。 如果需要使用显卡&#xff0c;还需要进行相关驱动的安装&#xff08;如使用的为Nvidia显卡&#xff0c;就需要安装相关的Nvidia显卡驱动&#xff…

Sqoop导入MySQL中含有回车换行符的数据

个人博客地址&#xff1a;Sqoop导入MySQL中含有回车换行符的数据 MySQL中的数据如下图&#xff1a; 检查HDFS上的目标文件内容可以看出&#xff0c;回车换行符位置的数据被截断了&#xff0c;导致数据列错位。 Sqoop提供了配置参数&#xff0c;在导入时丢弃掉数据的分隔符&…

掌握API和控制点(从Java到JNI接口)_36 JNI开发与NDK 04

4、 *.so的入口函数&#xff1a;JNI_OnLoad() VM (virtual machine)的角色 Java代码在VM上执行。在执行Java代码的过程中&#xff0c;如果Java需要与本地代码(*.so)沟通时&#xff0c; VM就会把*.so視为插件<Tn>而加载到VM里。然后让Java函数呼叫到这插件<Tn>里的…

[MRCTF2020]Ez_bypass1(md5绕过)

[MRCTF2020]Ez_bypass1(md5绕过) ​​ 这道题就是要绕过md5强类型比较&#xff0c;但是本身又不相等&#xff1a; md5无法处理数组&#xff0c;如果传入的是数组进行md5加密&#xff0c;会直接放回NULL&#xff0c;两个NuLL相比较会等于true&#xff1b; 所以?id[]1&gg…

90,【6】攻防世界 WEB Web_php_unserialize

进入靶场 进入靶场 <?php // 定义一个名为 Demo 的类 class Demo { // 定义一个私有属性 $file&#xff0c;默认值为 index.phpprivate $file index.php;// 构造函数&#xff0c;当创建类的实例时会自动调用// 接收一个参数 $file&#xff0c;用于初始化对象的 $file 属…

Jenkins安装部署(以及常见报错解决方案),jdk版本控制器sdkman

目录 零、环境介绍 一、Jenkins安装 1、插件安装以及更换插件源 2、修改jenkins时区 二、sdkman安装&#xff08;可选&#xff09; 1、sdkman常用方法 2、sdkman常用方法演示 2.1、查看可用的jdk 2.2、下载jdk并切换版本 三、jenkins报错解决 1、下载sdkman后systemc…

c语言练习题【数据类型、递归、双向链表快速排序】

练习1&#xff1a;数据类型 请写出以下几个数据的数据类型 整数 a a 的地址 存放a的数组 b 存放a的地址的数组 b的地址 c的地址 指向 printf 函数的指针 d 存放 d的数组 整数 a 的类型 数据类型是 int a 的地址 数据类型是 int*&#xff08;指向 int 类型的指针&#xff09; …

联想拯救者Y9000P IRX8 2023 (82WK) 原厂Win11 家庭中文版系统 带一键还原功能 安装教程

安装完重建winre一键还原功能&#xff0c;和电脑出厂时的系统状态一模一样。自动机型专用软件&#xff0c;全部驱动&#xff0c;主题壁纸&#xff0c;自动激活&#xff0c;oem信息等。将电脑系统完全恢复到出厂时状态。 支持机型 (MTM) : 82WK 系统版本&#xff1a;Windows 1…

深入解析“legit”的地道用法——从俚语到正式表达:Sam Altman用来形容DeepSeek: legit invigorating(真的令人振奋)

深入解析“legit”的地道用法——从俚语到正式表达 一、引言 在社交媒体、科技圈甚至日常对话中&#xff0c;我们经常会看到或听到“legit”这个词。比如最近 Sam Altman 在 X&#xff08;原 Twitter&#xff09;上发的一条帖子中写道&#xff1a; we will obviously deliver …

Vue 图片引用方式详解:静态资源与动态路径访问

目录 前言1. 引用 public/ 目录2. assets/ 目录3. 远程服务器4. Vue Router 动态访问5. 总结6. 扩展&#xff08;图片不显示&#xff09; 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF 在 Vue 开发中&#x…

DeepSeek-R1 本地部署教程(超简版)

文章目录 一、DeepSeek相关网站二、DeepSeek-R1硬件要求三、本地部署DeepSeek-R11. 安装Ollama1.1 Windows1.2 Linux1.3 macOS 2. 下载和运行DeepSeek模型3. 列出本地已下载的模型 四、Ollama命令大全五、常见问题解决附&#xff1a;DeepSeek模型资源 一、DeepSeek相关网站 官…

JVM运行时数据区域-附面试题

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域 有各自的用途&#xff0c;以及创建和销毁的时间&#xff0c;有的区域随着虚拟机进程的启动而一直存在&#xff0c;有些区域则是 依赖用户线程的启动和结束而建立和销毁。 1. 程序计…

2月3日星期一今日早报简报微语报早读

2月3日星期一&#xff0c;农历正月初六&#xff0c;早报#微语早读。 1、多个景区发布公告&#xff1a;售票数量已达上限&#xff0c;请游客合理安排行程&#xff1b; 2、2025春节档总票房破70亿&#xff0c;《哪吒之魔童闹海》破31亿&#xff1b; 3、美宣布对中国商品加征10…

C++ Primer 标准库vector

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.6 广播机制核心算法:维度扩展的数学建模

2.6 广播机制核心算法&#xff1a;维度扩展的数学建模 目录/提纲 #mermaid-svg-IfELXmhcsdH1tW69 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-IfELXmhcsdH1tW69 .error-icon{fill:#552222;}#mermaid-svg-IfELXm…

【Elasticsearch】硬件资源优化

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

bootstrap.yml文件未自动加载问题解决方案

在添加bootstrap.yml文件后,程序未自动扫描到,即图标是这样的: 查了一些资料,是缺少bootstrap相关依赖,虽然已经添加了spring-cloud-context依赖,但是这个依赖并未引入bootstrap依赖,可能是版本问题,需要手动引入 <dependency><groupId>org.springframework.cloud&…

C++底层学习预备:模板初阶

文章目录 1.编程范式2.函数模板2.1 函数模板概念2.2 函数模板原理2.3 函数模板实例化2.3.1 隐式实例化2.3.2 显式实例化 2.4 模板参数的匹配原则 3.类模板希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力&#xff01; 进入STL库学习之前我们要先了解有关模板的…