前言
本文将展示一段结合 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();