Blogger Information
Blog 12
fans 0
comment 1
visits 12559
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
轮播图示例及购物车示例
月缺
Original
940 people have browsed it

轮播图示例及购物车示例

轮播图

html部分

  1. <div class="container">
  2. <!-- 1. 图片组 -->
  3. <div class="img-group"></div>
  4. <!-- 2. 图片中下部的小按钮 -->
  5. <div class="btn-group"></div>
  6. <!-- 3. 翻页 -->
  7. <div class="skip">
  8. <a class="prev">&lt;</a>
  9. <a class="next">&gt;</a>
  10. </div>
  11. </div>

css部分

  1. /* 初始化 */
  2. * {
  3. margin: 0;
  4. padding: 0;
  5. box-sizing: border-box;
  6. }
  7. a {
  8. text-decoration: none;
  9. }
  10. /* 轮播图的容器 */
  11. .container {
  12. width: 62.5em;
  13. height: 22em;
  14. margin: 1em auto;
  15. /* 转为定位元素/定位父级 */
  16. position: relative;
  17. }
  18. .container:hover {
  19. cursor: pointer;
  20. }
  21. /* 图片组 */
  22. .container > .img-group img {
  23. width: 100%;
  24. height: 100%;
  25. border-radius: 0.6em;
  26. /* 默认全部隐藏 */
  27. display: none;
  28. /* 将所有的图片进行绝对定位,确保每一次只看到一张,所有图片共享这个容器 */
  29. position: absolute;
  30. left: 0;
  31. top: 0;
  32. }
  33. /* 设置默认显示的图片(第一张) */
  34. .container > .img-group img.active {
  35. display: block;
  36. }
  37. /* 按钮组(独立按钮) */
  38. .container > .btn-group {
  39. position: absolute;
  40. left: 0;
  41. right: 0;
  42. bottom: 1rem;
  43. /* 水平居中 */
  44. text-align: center;
  45. }
  46. .container > .btn-group span {
  47. /* 转成行内块元素: 即能水平排列,双支持宽度设置 */
  48. display: inline-block;
  49. padding: 0.5em;
  50. margin: 0 0.2em;
  51. background-color: #fff;
  52. border-radius: 50%;
  53. }
  54. .container > .btn-group span:hover {
  55. cursor: pointer;
  56. }
  57. .container > .btn-group .active {
  58. background-color: #10d1f3;
  59. }
  60. /* 翻页按钮 */
  61. .container .skip a {
  62. position: absolute;
  63. width: 2.5rem;
  64. height: 2.5rem;
  65. line-height: 2.5rem;
  66. border-radius: 50%;
  67. text-align: center;
  68. opacity: 0.3;
  69. top: 9rem;
  70. font-weight: lighter;
  71. font-size: 2rem;
  72. background-color: #787373;
  73. }
  74. .container .skip .prev {
  75. left: 1rem;
  76. }
  77. .container .skip .next {
  78. right: 1rem;
  79. }
  80. .container .skip *:hover {
  81. opacity: 0.6;
  82. color: #666;
  83. }

js部分

  1. class Swiper {
  2. constructor(imgs, code, imgcode, btncode) {
  3. this.imgs = imgs;
  4. this.code = code;
  5. this.imgcode = imgcode;
  6. this.btncode = btncode;
  7. this.next = null;
  8. this.prev = null;
  9. this.timer = null;
  10. this.clickEvent = new Event("click");
  11. }
  12. init() {
  13. this.next = document.querySelector(".skip .next");
  14. this.prev = document.querySelector(".skip .prev");
  15. this.next.addEventListener('click', ()=>this.nextImg());
  16. this.prev.addEventListener('click', ()=>this.prevImg());
  17. // 1. 生成轮播图所有图片
  18. this.createImgs(this.imgcode, this.imgs.length);
  19. // 2. 生成与轮播图数量对应的小按钮
  20. this.createBtns(this.btncode, this.imgs.length);
  21. this.autoPlay();
  22. // 鼠标移入时停止自动播放,移出时启动自动播放
  23. this.code.addEventListener("mouseover", ()=>this.stopPlay());
  24. this.code.addEventListener("mouseout", ()=>this.autoPlay());
  25. }
  26. // 生成图片
  27. createImgs(parent, length) {
  28. // 正确的做法, 应该是将所有图片,先在内存中创建,然后再统一的插入到页面中, 这样就只需要渲染一次dom一次
  29. // 文档片断元素
  30. const frag = document.createDocumentFragment();
  31. for (let i = 0; i < length; i++) {
  32. const img = document.createElement("img");
  33. img.src = this.imgs[i];
  34. img.alt = `banner${i + 1}`;
  35. // 为每一张图片添加一个自定义属性"data-index", 用它与小按钮进行绑定
  36. img.dataset.index = `${i + 1}`;
  37. if (i === 0) img.classList.add("active");
  38. // 内存中执行了四次
  39. frag.append(img);
  40. }
  41. // 页面中只渲染了一次,效率杠杠的
  42. parent.append(frag);
  43. }
  44. // 生成按钮
  45. createBtns(parent, length) {
  46. const frag = document.createDocumentFragment();
  47. for (let i = 0; i < length; i++) {
  48. const span = document.createElement("span");
  49. span.dataset.index = `${i + 1}`;
  50. if (i === 0) span.classList.add("active");
  51. // 给新生成的按钮,添加点击事件,用来切换图片
  52. span.onclick = ev => this.showImgs(ev);
  53. frag.append(span);
  54. }
  55. parent.append(frag);
  56. }
  57. // 按钮事件
  58. showImgs(ev) {
  59. // 1. 获取所有图片和按钮
  60. const imgArr = this.imgcode.querySelectorAll("img");
  61. const btnArr = this.btncode.querySelectorAll("span");
  62. // 2. 因为我们要根据用户的点击确定当前应该显示哪一个,所以应该将之前的激活全部取消掉
  63. // 但是我们又不知道当前是哪个处于激活状态, 全部过一遍
  64. // btnArr.forEach(item => {
  65. // if (item.classList.contains("active")) item.classList.remove("active");
  66. // });
  67. // imgArr.forEach(item => {
  68. // if (item.classList.contains("active")) item.classList.remove("active");
  69. // });
  70. // 将上面二段代码合并
  71. [btnArr, imgArr].forEach(items => {
  72. items.forEach(item => {
  73. if (item.classList.contains("active")) item.classList.remove("active");
  74. });
  75. // 3. 再给当前正在点击的按钮添加激活,然后再根据当前激活的按钮确定应该显示哪一张图片
  76. ev.target.classList.add("active");
  77. imgArr.forEach(img => {
  78. // 这张应该显示的图片的data-index应该与按钮 的data-index相等,就显示出来
  79. if (ev.target.dataset.index === img.dataset.index) img.classList.add("active");
  80. });
  81. });
  82. }
  83. // 翻页事件
  84. // 向前翻页
  85. prevImg() {
  86. //1. 当前图片和当前的按钮
  87. const currentImg = this.imgcode.querySelector("img.active");
  88. const currentBtn = this.btncode.querySelector("span.active");
  89. // 2. 去掉当前图片和按钮的激活样式
  90. currentImg.classList.remove("active");
  91. currentBtn.classList.remove("active");
  92. // 3. 获取当前图片和按钮的前一个兄弟元素
  93. const prevImg = currentImg.previousElementSibling;
  94. const prevBtn = currentBtn.previousElementSibling;
  95. // 4. 判断,如果存在前一张图片,就设置为激活
  96. if (prevImg !== null && prevBtn !== null) {
  97. prevImg.classList.add("active");
  98. prevBtn.classList.add("active");
  99. } else {
  100. // 将最后一个图片设置为激活显示,实现循环显示
  101. this.imgcode.lastElementChild.classList.add("active");
  102. this.btncode.lastElementChild.classList.add("active");
  103. }
  104. }
  105. // 向后翻页
  106. nextImg() {
  107. //1. 当前图片和当前的按钮
  108. const currentImg = this.imgcode.querySelector("img.active");
  109. const currentBtn = this.btncode.querySelector("span.active");
  110. // 2. 去掉当前图片和按钮的激活样式
  111. currentImg.classList.remove("active");
  112. currentBtn.classList.remove("active");
  113. // 3. 获取当前图片和按钮的前一个兄弟元素
  114. const nextImg = currentImg.nextElementSibling;
  115. const nextBtn = currentBtn.nextElementSibling;
  116. // 4. 判断,如果存在前一张图片,就设置为激活
  117. if (nextImg !== null && nextBtn !== null) {
  118. nextImg.classList.add("active");
  119. nextBtn.classList.add("active");
  120. } else {
  121. // 将最后一个图片设置为激活显示,实现循环显示
  122. this.imgcode.firstElementChild.classList.add("active");
  123. this.btncode.firstElementChild.classList.add("active");
  124. }
  125. }
  126. // 自动播放
  127. autoPlay() {
  128. const self = this;
  129. // ev: 事件对象,在方法总是有效的
  130. this.timer = setInterval(() => {
  131. // console.log(this.next);
  132. this.next.dispatchEvent(this.clickEvent, self.nextImg);
  133. }, 2000);
  134. }
  135. // 自动停止
  136. stopPlay() {
  137. clearInterval(this.timer);
  138. }
  139. }
  140. const imgs = ["images/banner_1.jpg", "images/banner_2.jpg", "images/banner_3.jpg", "images/banner_4.jpg"];
  141. const container = document.querySelector(".container");
  142. // 图片组
  143. const imgGroup = document.querySelector(".container > .img-group");
  144. // 按钮组
  145. const btnGroup = document.querySelector(".container > .btn-group");
  146. // 提供4个参数: 图片数组、轮播图盒子节点元素、图片组盒子节点元素、轮播图底部按钮节点
  147. const swiper = new Swiper(imgs, container, imgGroup, btnGroup);
  148. window.onload = () => swiper.init();

成品效果

轮播图

购物车

html部分

  1. <table>
  2. <caption>
  3. 我的购物车
  4. </caption>
  5. <thead>
  6. <th><input type="checkbox" name="checkAll" id="check-all" checked /><label for="check-all">全选</label></th>
  7. <th>图片</th>
  8. <th>品名</th>
  9. <th>单位</th>
  10. <th>单价/元</th>
  11. <th>数量</th>
  12. <th>金额/元</th>
  13. </thead>
  14. <tbody>
  15. <tr>
  16. <td>
  17. <input type="checkbox" name="item" class="item" value="SN-1020" checked />
  18. </td>
  19. <td>
  20. <a href=""><img src="images/p1.png" alt="" /></a>
  21. </td>
  22. <td>JavaScript权威指南(第七版)</td>
  23. <td></td>
  24. <td class="price">100</td>
  25. <td><input type="number" min="1" value="1" /></td>
  26. <td class="amount">0</td>
  27. </tr>
  28. <tr>
  29. <td>
  30. <input type="checkbox" name="item" class="item" value="SN-1020" checked />
  31. </td>
  32. <td>
  33. <a href=""><img src="images/p2.png" alt="" /></a>
  34. </td>
  35. <td>JavaScript高级程序设计(第四版)</td>
  36. <td></td>
  37. <td class="price">129</td>
  38. <td><input type="number" min="1" value="1" /></td>
  39. <td class="amount">0</td>
  40. </tr>
  41. <tr>
  42. <td>
  43. <input type="checkbox" name="item" class="item" value="SN-1030" checked />
  44. </td>
  45. <td>
  46. <a href=""><img src="images/p3.png" alt="" /></a>
  47. </td>
  48. <td>JavaScript忍者秘籍(第二版)</td>
  49. <td></td>
  50. <td class="price">99</td>
  51. <td><input type="number" min="1" value="1" /></td>
  52. <td class="amount">0</td>
  53. </tr>
  54. <tr>
  55. <td>
  56. <input type="checkbox" name="item" class="item" value="SN-1040" checked />
  57. </td>
  58. <td>
  59. <a href=""><img src="images/p4.png" alt="" /></a>
  60. </td>
  61. <td>ThinkPad X1 Carbon 2021</td>
  62. <td></td>
  63. <td class="price">12999</td>
  64. <td><input type="number" min="1" value="1" /></td>
  65. <td class="amount">0</td>
  66. </tr>
  67. <tr>
  68. <td>
  69. <input type="checkbox" name="item" class="item" value="SN-1050" checked />
  70. </td>
  71. <td>
  72. <a href=""><img src="images/p5.png" alt="" /></a>
  73. </td>
  74. <td>MacBook Pro 16 10代i7 16G 512G</td>
  75. <td></td>
  76. <td class="price">23800</td>
  77. <td><input type="number" min="1" value="1" /></td>
  78. <td class="amount">0</td>
  79. </tr>
  80. </tbody>
  81. <tfoot>
  82. <tr>
  83. <td colspan="5">总计:</td>
  84. <td id="sum">0</td>
  85. <td id="total-amount">0</td>
  86. </tr>
  87. </tfoot>
  88. </table>

css部分

  1. * {
  2. margin: 0;
  3. padding: 0;
  4. box-sizing: border-box;
  5. }
  6. html {
  7. font-size: 10px;
  8. }
  9. box {
  10. font-size: 1.6rem;
  11. }
  12. table {
  13. border-collapse: collapse;
  14. width: 90%;
  15. text-align: center;
  16. margin: 1rem auto;
  17. color: #666;
  18. }
  19. table caption {
  20. margin-bottom: 1rem;
  21. font-size: 2rem;
  22. }
  23. table th,
  24. table td {
  25. padding: 0.5rem;
  26. font-weight: normal;
  27. }
  28. table thead tr:first-of-type {
  29. background-color: rgb(26, 187, 187);
  30. height: 3rem;
  31. color: white;
  32. }
  33. table thead tr:first-of-type:hover {
  34. opacity: 0.8;
  35. cursor: pointer;
  36. }
  37. table input[type="checkbox"] {
  38. width: 1rem;
  39. height: 1rem;
  40. }
  41. /* table tr:nth-of-type(even) {
  42. background-color: #eee;
  43. } */
  44. table tbody tr:hover {
  45. background-color: lightcyan;
  46. transition: 0.5s;
  47. cursor: pointer;
  48. }
  49. table input[type="number"] {
  50. height: 2em;
  51. width: 4em;
  52. border: none;
  53. border-bottom: 1px solid;
  54. outline: none;
  55. text-align: center;
  56. }
  57. /* table input[type="number"]:focus {
  58. background-color: rgb(26, 187, 187);
  59. } */
  60. tbody img {
  61. width: 3em;
  62. transition: all 0.6s;
  63. cursor: pointer;
  64. }
  65. tbody img:hover {
  66. transform: scale(4);
  67. }
  68. tfoot tr {
  69. height: 3rem;
  70. color: coral;
  71. background-color: lightcyan;
  72. }
  73. button {
  74. width: 15rem;
  75. height: 2rem;
  76. outline: none;
  77. border: none;
  78. background-color: rgb(26, 187, 187);
  79. color: white;
  80. letter-spacing: 5px;
  81. }
  82. button:hover {
  83. background-color: coral;
  84. transition: 0.2s;
  85. cursor: pointer;
  86. }
  87. @media screen and (min-width: 400px) {
  88. html {
  89. font-size: 12px;
  90. }
  91. }
  92. @media screen and (min-width: 600px) {
  93. html {
  94. font-size: 14px;
  95. }
  96. }
  97. @media screen and (min-width: 800px) {
  98. html {
  99. font-size: 16px;
  100. }
  101. }

js部分

  1. // 功能一: 完成全选和全不选功能
  2. // 1. 全选复选框
  3. const checkAll = document.querySelector("#check-all");
  4. // 2. 每个商品的复选框
  5. const checkItems = document.getElementsByName("item");
  6. // ==========================================================
  7. // 功能二: 自动计算
  8. // 分析: 所有的计算,都是基于"数量的变化", 第一步就要获取到所有商品数量控件
  9. const numInput = document.querySelectorAll('input[type="number"]');
  10. // 给每一个数量控件绑定一个change事件,进行监听它的变量
  11. // 当控件的值发生变化时, 自动进行重新 计算
  12. numInput.forEach(input => (input.onchange = autoTotal));
  13. // 当页面加载完成时,应该将自动计算函数执行一次(初始化)
  14. window.onload = autoCalculate;
  15. function autoCalculate() {
  16. // 1. 获取每个商品的金额, 金额 = 数量 * 单价
  17. // 数量, 当前有多个商品,所以应该返回一个由数量组成的集合/数组
  18. const numbers = document.querySelectorAll('input[type="number"]');
  19. // console.log(numbers);
  20. // [...numbers].forEach(num => console.log(typeof parseInt(num.value)));
  21. // [...numbers].forEach(num => console.log(num.value * 1));
  22. //map()代替forEach: 因为forEach()没有返回值,map()功能与forEach一样的,但是有一个数组返回值
  23. const numArr = [...numbers].map(num => num.value * 1);
  24. // 获取单价组成的数组
  25. const prices = document.querySelectorAll("tbody .price");
  26. // console.log(prices);
  27. const priceArr = [...prices].map(price => price.textContent * 1);
  28. // console.log(numArr, priceArr);
  29. // 每一个商品与单价的乘积是它的金额,有多个商品,所以应该返回 一个由"金额"组成的数组
  30. // reduce()
  31. const amountArr = [priceArr, numArr].reduce((prev, curr) => prev.map((item, key) => item * curr[key]));
  32. // console.log(amountArr);
  33. // 2. 商品总数
  34. let sum = numArr.reduce((prev, curr) => prev + curr);
  35. // 3. 所有商品总金额
  36. let total = amountArr.reduce((prev, curr) => prev + curr);
  37. // 4. 将以上的计算结果,渲染到页面中
  38. // forEach(function(正在遍历的元素,该元素的索引,数组))
  39. document.querySelectorAll(".amount").forEach((item, index) => (item.textContent = amountArr[index]));
  40. document.querySelector("#sum").textContent = sum;
  41. document.querySelector("#total-amount").textContent = total;
  42. }
  43. // 全选时
  44. checkAll.onchange = (ev) => {
  45. checkItems.forEach(item => (item.checked = ev.target.checked));
  46. if (!ev.target.checked) {
  47. document.querySelector("#sum").textContent = 0;
  48. document.querySelector("#total-amount").textContent = 0;
  49. } else {
  50. autoCalculate()
  51. }
  52. }
  53. // 选择某个商品时, 数量,总金额实时更新
  54. function autoTotal() {
  55. // 1. 获取每个商品的金额, 金额 = 数量 * 单价
  56. // 数量, 当前有多个商品,所以应该返回一个由数量组成的集合/数组
  57. const numbers = document.querySelectorAll('input[type="number"]');
  58. const checkeds = [...checkItems].filter((item, idx) => {
  59. if (item.checked) {
  60. item.dataset.checkidx = idx;
  61. return true;
  62. }
  63. return false;
  64. }).map((item) => item.dataset.checkidx);
  65. const numArr = [...numbers].filter((v, idx) => checkeds.includes(`${idx}`)).map(num => num.value * 1);
  66. console.log([...numbers].filter((v, idx) => checkeds.includes(`${idx}`)));
  67. // 获取单价组成的数组
  68. const prices = document.querySelectorAll("tbody .price");
  69. const priceArr = [...prices].filter((v, idx) => checkeds.includes(`${idx}`)).map(price => price.textContent * 1);
  70. const amountArr = [priceArr, numArr].reduce((prev, curr) => prev.map((item, key) => item * curr[key]));
  71. // 2. 商品总数
  72. let sum = numArr.reduce((prev, curr) => prev + curr);
  73. // 3. 所有商品总金额
  74. let total = amountArr.reduce((prev, curr) => prev + curr);
  75. // 4. 将以上的计算结果,渲染到页面中
  76. document.querySelector("#sum").textContent = sum;
  77. document.querySelector("#total-amount").textContent = total;
  78. }
  79. checkItems.forEach((item)=> item.onchange = ()=>{
  80. // 全选复选框选中状态根据所有商品的复选框状态更改
  81. checkAll.checked = [...checkItems].every(item => item.checked);
  82. autoTotal();
  83. });

成品效果

购物车

```

Correcting teacher:天蓬老师天蓬老师

Correction status:qualified

Teacher's comments:class是function的语法糖,封装的很不错
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post