商品列表及商品详情展示

前言

本文将展示一段结合 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 字符串设置为 productContentinnerHTML,从而在页面上显示商品。
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 内容。
    • 最后更新 productContentinnerHTML 以显示搜索结果。
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();
相关推荐
wn53120 分钟前
【浏览器 - Mac实时调试iOS手机浏览器页面】
前端·macos·ios·智能手机·浏览器
LCG元1 小时前
Vue.js组件开发-实现HTML内容打印
前端·vue.js·html
engchina2 小时前
CSS 图像、媒体和表单元素的样式化指南
前端·css
�时过境迁,物是人非2 小时前
Redis地理散列GeoHash
前端·redis·bootstrap
山禾女鬼0012 小时前
深入探索 HTML5 拖拽效果 API:打造流畅交互体验
前端·html·html5
shenyaofeng4 小时前
React 封装高阶组件 做路由权限控制
前端·javascript·react.js·职场和发展·typescript
字节全栈_PVK5 小时前
微服务配置中心 Apollo解析——Portal 关联 Namespace
java·前端·微服务
MarisolHu5 小时前
vue2项目(一)
开发语言·前端·javascript·vue.js
CaraYQ5 小时前
【vue项目权限控制方案】
前端·vue.js·状态模式