js实战:选项卡、购物车、轮播图、懒加载效果
发布于:2022-02-09 10:20:29
次阅读
1. 实例演示选项卡功能
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>实战: 选项卡效果</title> </head> <body> <style> .tabs { width: 12em; display: grid; grid-template-columns: repeat(3, 1fr); } .tabs li { list-style: none; padding: 0.5em 1em; } .tabs li:hover { cursor: pointer; } .content { display: none; } .tabs .active { background-color: cyan; } .content.active { display: block; } </style> <div class="box"> <!-- 选项卡 --> <!-- 利用冒泡只需在ul设置事件 --> <ul class="tabs" onclick="show()"> <!-- 每个列表加自定义属性,记录序号,点击后验证是点哪个列表,显示对应的内容 --> <li data-index="1" class="active">体育</li> <li data-index="2">科技</li> <li data-index="3">探索</li> </ul> <!-- 体育选项卡内容 --> <ul class="content active" data-index="1"> <li><a href="">12强赛-国足0-2完败日本 7战5分出线希望愈发渺茫</a></li> <li><a href="">王燊超封堵时手触球送点 越南队7战0分提前出局</a></li> <li><a href="">国足官方宣布郭田雨留洋 朱艺:维泽拉最高中锋仅1米</a></li> <li><a href="">巴萨起诉前任主席巴托梅乌 经纪人表态登贝莱愿留队</a></li> <li><a href="">李雯雯:回家过年因8点起床挨骂</a></li> </ul> <!-- 科技选项卡内容 --> <ul class="content" data-index="2"> <li><a href="">腾讯申请微信键盘商标被驳回</a></li> <li><a href="">高途教育经营新增职业中介活动</a></li> <li><a href="">美国加州将为工人延长带薪病假</a></li> <li><a href="">证监会坐实零跑汽车境外IPO传闻</a></li> <li><a href="">常规电视剧剧集正片时长不能少于41分</a></li> </ul> <!-- 探索选项卡内容 --> <ul class="content" data-index="3"> <li><a href="">这场大火已经燃烧了6000年</a></li> <li><a href="">为什么电流会有嗡嗡响怪声音?</a></li> <li><a href="">为什么说人类正输给超级细菌?</a></li> <li><a href="">它一生可能只活5年,3.75年都在睡觉!</a></li> <li><a href="">汤加火山爆发在地球另一端引发海啸</a></li> </ul> </div> <script> function show() { // 1. 选项卡切换效果 // 使用event.currentTarget获取事件绑定元素,即ul,包含li // 使用...转为数组,forEach方法遍历li元素,移除active样式 [...event.currentTarget.children].forEach((li) => li.classList.remove("active") ); // 当前点击的标签加active样式 // 用event.target获取事件触发元素 event.target.classList.add("active"); // 2.内容显示效果 // 移除当前显示内容的active样式 // 方法同选项卡,用遍历 document .querySelectorAll(".content") .forEach((li) => li.classList.remove("active")); // 显示自定义属性相同的内容 [...document.querySelectorAll(".content")] .find((ul) => ul.dataset.index === event.target.dataset.index) .classList.add("active"); } </script> </body></html>
2. 购物车
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>购物车</title> </head> <body> <style> .selectAll { margin-top: 1em; margin-left: 0.7em; } .selectAll *:hover { cursor: pointer; } .shopingList { padding: 0; width: 35em; background-color: lightskyblue; } .shopingList > li { width: 35em; display: grid; grid-template-columns: 3.5em repeat(5, 5fr); border-bottom: 1px solid rgb(12, 63, 105); } .shopingList > li:nth-of-type(1) { color: #eee; background-color: rgb(12, 63, 105); } li:last-of-type span:nth-of-type(1) { text-align: center; grid-column: 1 / span 5; } li:nth-of-type(n + 2):hover, li input[type="checkbox"] { cursor: pointer; background-color: rgb(135, 194, 250); } h4, span { margin: 0.2em 0.6em; } h4 { padding: 0.3em 0; } input[type="number"] { width: 70%; outline: none; } </style> <div class="box"> <!-- 全选框 --> <div class="selectAll"> <input type="checkbox" onchange="checkAll(),autoCount()" name="check-all" id="check-all" /> <label for="check-all">全选</label> </div> <ul class="shopingList"> <li> <h4>选择</h4> <h4>品名</h4> <h4>数量</h4> <h4>单位</h4> <h4>单价(元)</h4> <h4>金额(元)</h4> </li> <li> <span><input type="checkbox" /> </span> <span>土豆</span> <span><input type="number" value="1" min="1" class="num" /></span> <span>斤</span> <span class="price">3.5</span> <span class="amount">0</span> </li> <li> <span><input type="checkbox" /> </span> <span>土猪肉</span> <span><input type="number" value="1" min="1" class="num" /></span> <span>斤</span> <span class="price">24</span> <span class="amount">0</span> </li> <li> <span><input type="checkbox" /> </span> <span>啤酒</span> <span><input type="number" value="1" min="1" class="num" /></span> <span>瓶</span> <span class="price">6.8</span> <span class="amount">0</span> </li> <li> <span>合计</span> <span class="total-amount">2</span> </li> </ul> </div> </body> <script> // 1. 实现全选功能 function checkAll() { // 获取触发事件的选择框状态; let checkbox_status = event.target.checked; // 定义数组,获取所有商品选择框元素 const checkbox_goods = document.querySelectorAll( ".shopingList input[type=checkbox]" ); // 遍历商品选择框数组设为选择状态 checkbox_goods.forEach((i) => (i.checked = checkbox_status)); } // 2. 根据每个商品选择状态来设置全选; function checkbox() { // 获取所有商品的选择框元素; const checkbox_goods = document.querySelectorAll( ".shopingList input[type=checkbox]" ); // 用数组的every方法判断所有选择框是否全是选中状态,返回true,定义变量存放 // 此处要注意,checkbox_goods不是数组,用...转为数组 let checkbox_goods_status = [...checkbox_goods].every( (i) => i.checked === true ); // 给全选框赋值 document.querySelector("#check-all").checked = checkbox_goods_status; } // 3. 商品的自动计算 // 单个商品的计算基于数量改变 // 合计计算基于所选择的商品 // 思路:先定义计算单个商品、计算合计两个函数 // 定义自动计算单个商品函数 // 定义自动计算合计函数 // 打开购物车时,判断勾选调用自动计算 // 商品数量变化时,判断勾选调用自动计算 // 勾选变化时调用自动计算 // 定义数组常量:记录商品数量元素。考虑后面要给每个元素加商品数量改变事件。 const input_nums = document.querySelectorAll(".num"); // 计算每个商品的金额函数:参数为数量数组,单价数组 function singleAmount(numArr, priceArr) { // 用数组函数map遍历数量数组numArr计算金额 return numArr.map( (goods_num, num_index) => parseFloat(goods_num) * parseFloat(priceArr[num_index]) ); } // 计算合计金额的函数:参数为每个商品金额数组 function totalAmount(amountArr) { // 用数组函数reduce遍历金额数组累加 return amountArr.reduce((total_value, amount) => total_value + amount); } // 自动计算函数 function autoCount() { // 获取商品数量数组:数量元素转为数组,map遍历,再取每个元素的值 const goods_nums_Arr = [...input_nums].map( (input_num) => input_num.value ); // 获取商品单价元素 const prices_elements = document.querySelectorAll(".price"); // 商品单价数组:方法同上,取每个元素的文字内容,用parseFloat函数转为浮点数字 const goods_price_Arr = [...prices_elements].map((prices_element) => parseFloat(prices_element.textContent) ); // 每个商品金额数组 const goods_single_amount_Arr = singleAmount( goods_nums_Arr, goods_price_Arr ); // 获取每个商品全额元素,遍历每个元素,元素的文字内容设置为对应索引金额 document .querySelectorAll(".amount") .forEach( (amount_element, index) => (amount_element.textContent = goods_single_amount_Arr[index]) ); // 获取选择框元素 const checked_elementArr = [ ...document.querySelectorAll(".shopingList input[type=checkbox]"), ]; // 定义要统计合计的金额数组 let count_goods_single_amount_Arr = []; // 定义合计元素变量 const total_amount_element = document.querySelector(".total-amount"); // 遍历选择框元素,勾选的,通过索引获取对应商品金额数组的数值组成新数组 checked_elementArr.forEach((element, index) => { if (element.checked === true) { count_goods_single_amount_Arr.push(goods_single_amount_Arr[index]); } }); // 计算并输出显示合计 document.querySelector(".total-amount").textContent = count_goods_single_amount_Arr.length > 0 ? totalAmount(count_goods_single_amount_Arr) : 0; } // 加载购物车时调用自动计算 window.onload = autoCount; // 商品数量变化时调用自动计算 // 要先给每个商品定义onchange事件 input_nums.forEach((element) => (element.onchange = autoCount)); // 监听选择框状态变化事件,调用自动计算。 [...document.querySelectorAll(".shopingList input[type=checkbox]")].forEach( (element) => (element.onchange = () => { checkbox(); autoCount(); }) ); </script></html>
3. 轮播图
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>轮播图</title> </head> <body> <style> .box { min-width: 30%; max-width: 60%; margin: 30px auto; padding: 0 10px; } .box .imgs { /* height: 30%; */ } .box .imgs img { height: 100%; width: 100%; border-radius: 10px; display: none; } .box .imgs img.active { display: block; } .box .btns { display: flex; place-content: center; } .box .btns span { width: 8px; height: 8px; background-color: rgba(255, 255, 255, 0.5); border-radius: 50%; margin: -12px 3px 5px; } .box .btns span.active { background-color: rgb(1, 37, 90); } </style> <div class="box"> <div class="imgs"> <a href=""> <img src="https://img.alicdn.com/imgextra/i3/6000000002700/O1CN01IHv4w11Voe78qwWjW_!!6000000002700-0-octopus.jpg" data-index="1" class="active" /> </a> <a href=""> <img src="https://gtms03.alicdn.com/tps/i3/TB1gXd1JXXXXXapXpXXvKyzTVXX-520-280.jpg" data-index="2" /> </a> <a href=""> <img src="https://gtms01.alicdn.com/tps/i1/TB1r4h8JXXXXXXoXXXXvKyzTVXX-520-280.jpg" data-index="3" /> </a> <a href=""> <img src="https://gtms02.alicdn.com/tps/i2/TB10vPXKpXXXXacXXXXvKyzTVXX-520-280.jpg" data-index="4" /> </a> <a href=""> <img src="https://img.alicdn.com/imgextra/i4/6000000001102/O1CN01HJ1Qxo1K0lCQcyutq_!!6000000001102-0-octopus.jpg" data-index="5" /> </a> </div> <div class="btns"> <span data-index="1" class="active"></span> <span data-index="2"></span> <span data-index="3"></span> <span data-index="4"></span> <span data-index="5"></span> </div> </div> <script> // 一、点击按钮变换图片 // 1. 获取所有图片和按钮元素 const imgs = document.querySelectorAll(".box .imgs img"); const btns = document.querySelectorAll(".box .btns span"); // 给所有按钮添加事件 btns.forEach((btn) => (btn.onclick = setActive)); // 2. 定义按钮事件函数 function setActive() { // 清空所有图片和按钮的激活样式 imgs.forEach((img) => img.classList.remove("active")); btns.forEach((btn) => btn.classList.remove("active")); // 根据点击按钮的索引属性确定显示的图片 // 先设置点击按钮为激活状态 event.target.classList.add("active"); // 查找相应索引图片,并显示 imgs.forEach((img) => { if (img.dataset.index === event.target.dataset.index) { img.classList.add("active"); } }); } // 二、定时播放 // 设置定时器,模拟定时点击按钮 // setInterval:三个参数,回调函数;定时时间;传给回调函数的参数 // 用定时器第三个参数给回调函数传按钮数组的索引,用object.keys方法可取数组的索引为数组 setInterval( (btnArr) => { // 原理:给回调函数传递按钮数组的索引,根据索引模拟点击对应的按钮 // 用数组方法shift拿出第1个值,数组中就没有了该值 let index = btnArr.shift(); // 根据索引模拟点击,用事件派发dispatchEvent btns[index].dispatchEvent(new Event("click")); // 把当前索引放到数组后面 btnArr.push(index); }, 2000, Object.keys(btns) ); </script> </body></html>
4. 懒加载
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>懒加载</title> <style> h1 { font-size: 5em; } img { width: 100%; } </style> </head> <body> <h1>第1张图片</h1> <img data-src="https://img.alicdn.com/imgextra/i3/6000000002700/O1CN01IHv4w11Voe78qwWjW_!!6000000002700-0-octopus.jpg" /> <h1>第2张图片</h1> <img data-src="https://gtms03.alicdn.com/tps/i3/TB1gXd1JXXXXXapXpXXvKyzTVXX-520-280.jpg" /> <h1>第3张图片</h1> <img data-src="https://gtms01.alicdn.com/tps/i1/TB1r4h8JXXXXXXoXXXXvKyzTVXX-520-280.jpg" /> <h1>第4张图片</h1> <img data-src="https://gtms02.alicdn.com/tps/i2/TB10vPXKpXXXXacXXXXvKyzTVXX-520-280.jpg" /> <h1>第5张图片</h1> <img data-src="https://img.alicdn.com/imgextra/i4/6000000001102/O1CN01HJ1Qxo1K0lCQcyutq_!!6000000001102-0-octopus.jpg" /> </body> <script> // 图片位置在视口中时才加载显示 // 原理: // 把图片链接放在自定义属性data-src中 // 用getBoundingClientRect()方法返回元素的位置和大小 // 判断图片顶部位置是否小于视口高度window.innerHeight,小则将src属性设为data-src值 // 定义加载函数 function load() { // 取得所有图片转换为元素数组,遍历并判断位置,可用document.images对象 [...document.images].forEach((img) => { if (img.getBoundingClientRect().top < window.innerHeight) { img.src = img.dataset.src; } }); } // 定义页面加载事件 window.onload = load; // 定义窗口滚动事件 window.onscroll = load; </script></html>