前言
本文将展示一段结合 HTML、CSS 和 JavaScript 的代码,实现了一个简单的商品展示页面及商品详情,涵盖数据获取、渲染、搜索及排序等功能。
效果展示
点击不同的商品会展示对应的商品详情。
代码部分
代码总体实现
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;
//渲染originalData
render(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数据赋值给originalData
originalData = 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为productContent
let productContent = document.getElementById('productContent');
productContent.innerHTML = str_content;
});
// //最后渲染上去
// render(originalData);
// })
//========================排序==================
//获取按钮
let orderBut = document.getElementById('orderBut');
//初始化次数为零
let num = 0;
//给按钮上点击事件
orderBut.onclick = function() {
//次数+1
num++;
//如果次数等于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
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
html
* {
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
总览
javascript
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;
//渲染originalData
render(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数据赋值给originalData
originalData = 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为productContent
let productContent = document.getElementById('productContent');
productContent.innerHTML = str_content;
});
// //最后渲染上去
// render(originalData);
// })
//========================排序==================
//获取按钮
let orderBut = document.getElementById('orderBut');
//初始化次数为零
let num = 0;
//给按钮上点击事件
orderBut.onclick = function() {
//次数+1
num++;
//如果次数等于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
:用于存储原始商品数据,在搜索和排序操作中作为基础数据使用。
javascript
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
函数渲染原始数据。
- 使用
javascript
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
,从而在页面上显示商品。
javascript
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
,通常这个页面会从本地存储中读取商品详情数据并展示。
javascript
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
以显示搜索结果。
- 获取搜索框元素并添加
javascript
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
重新渲染商品展示区域。
- 获取 "排序" 按钮元素,并初始化一个计数器
javascript
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);
};
商品详情部分
代码部分
代码总体实现
html
<!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
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
html
* {
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
页面。
- 对于
- 获取元素 :
javascript
// 回主页的点击事件
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
,从而在页面上渲染出商品详情。
- 初始化一个空字符串
- 获取本地存储数据 :
javascript
//通过键名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()
函数,执行上述图片渲染操作。
javascript
//渲染函数(为了渲染图片的)
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();