批改状态:合格
老师批语:非常出色
table {border-collapse: collapse;width: 90%;text-align: center;margin: auto;}table caption {margin-bottom: 15px;font-size: 1.5rem;}table th,table td {border-bottom: 1px solid #ccc;padding: 5px;font-weight: normal;}table thead tr:first-of-type {background-color: #e6e6e6;height: 3em;}table input[type="checkbox"] {width: 1.5em;height: 1.5em;}table tbody tr {border-bottom: 1px solid #ccc;}table tbody tr:hover {background-color: #f6f6f6;cursor: pointer;}tbody img {width: 3em;}tbody input[type="number"] {width: 3em;}button {width: 150px;height: 30px;outline: none;border: none;background-color: teal;color: white;letter-spacing: 5px;}button:hover {opacity: 0.7;cursor: pointer;}
<table><caption>购物车</caption><thead><tr><!-- 全选复选框 --><th><input type="checkbox" name="checkAll" id="check-all" checked /><label for="check-all">全选</label></th><th>图片</th><th>品名</th><th>单位</th><th>单价/元</th><th>数量</th><th>金额/元</th></tr></thead><tbody><tr><td><input type="checkbox" name="item" value="SN-1020" checked /></td><td><a href=""><img src="images/p1.jpg" alt="" /></a></td><td>iPhone 11</td><td>台</td><td class="price">4799</td><td><input type="number" min="1" value="1" /></td><td class="amount">4799</td></tr><tr><td><input type="checkbox" name="item" value="SN-1020" checked /></td><td><a href=""><img src="images/p2.jpg" alt="" /></a></td><td>小米pro 11</td><td>部</td><td class="price">3999</td><td><input type="number" min="1" value="2" /></td><td class="amount">7998</td></tr><tr><td><input type="checkbox" name="item" value="SN-1030" checked /></td><td><a href=""><img src="images/p3.jpg" alt="" /></a></td><td>MacBook Pro</td><td>台</td><td class="price">18999</td><td><input type="number" min="1" value="1" /></td><td class="amount">18999</td></tr><tr><td><input type="checkbox" name="item" value="SN-1040" checked /></td><td><a href=""><img src="images/p4.jpg" alt="" /></a></td><td>小米75电视</td><td>台</td><td class="price">5999</td><td><input type="number" min="1" value="2" /></td><td class="amount">11998</td></tr><tr><td><input type="checkbox" name="item" value="SN-1050" checked /></td><td><a href=""><img src="images/p5.jpg" alt="" /></a></td><td>Canon 90D单反</td><td>台</td><td class="price">9699</td><td><input type="number" min="1" value="1" /></td><td class="amount">9699</td></tr></tbody><tfoot><tr style="font-weight: bolder; font-size: 1.2em"><td colspan="5">总计:</td><td id="sum">7</td><td id="total-amount">53493</td></tr></tfoot></table><div style="width: 90%; margin: 10px auto"><button style="float: right; width: 100px">结算</button></div>
// 1.获取全选按钮,每个独立的商品复选框const checkAll = document.querySelector('#check-all');const checkItems = document.getElementsByName("item");// 2. 将当前的全选的状态变化赋值给每个商品复选框checkAll.addEventListener('change', (ev) => {checkItems.forEach(item => {item.checked = ev.target.checked});// 根据选中状态计算商品的总金额和总数量amountTotal();});// 3. 为每个单独商品的复选框添加事件checkItems.forEach(item => {item.addEventListener('change', () => {checkAll.checked = [...checkItems].every(item => item.checked);// 根据选中状态计算商品的总金额和总数量amountTotal();})});// 4.为数量按钮添加事件,动态计算商品总量和金额const numInput = document.querySelectorAll('tbody input[type="number"]');numInput.forEach(input => input.addEventListener('change', autoCalculate));// 页面加载完成自动计算window.addEventListener('load', autoCalculate);// 5. 自动计算方法function autoCalculate() {// 获取所有商品单价节点const prices = document.querySelectorAll('tbody .price');// 获得所有商品单价金额const priceArr = [...prices].map(price => +price.innerText);console.log(priceArr);// 获取所有数量按钮节点const numbers = document.querySelectorAll('tbody input[type="number"]');// 获得所有商品数量数组const numArr = [...numbers].map(num => +num.value);console.log(numArr);// 计算单个商品金额 = 数量*单价let amountArr = [priceArr, numArr].reduce((total, curr) => {return total.map((item, index) => {return item * curr[index]})});// 将每一个商品金额渲染到页面中document.querySelectorAll('.amount').forEach((item, index) => {item.innerText = amountArr[index]})// 计算总数量总数量amountTotal();}// 根据复选框选中状态计算总金额和总数量function amountTotal() {// 获取所有数量按钮节点const numbers = document.querySelectorAll('tbody input[type="number"]');// 获得所有商品数量数组const numArr = [...numbers].map(num => {// 获取当前数量节点父节点下的check复选框const check = num.parentElement.parentElement.querySelector('input[type="checkbox"]');// 过滤出选中的商品数量数组return check.checked ? +num.value : 0;});console.log(numArr);// 获取所有单个商品总金额节点const amounts = document.querySelectorAll('.amount');// 获得所有单个商品总金额数组const amountArr = [...amounts].map(amount => {// 获取当前数量节点父节点下的check复选框const check = amount.parentElement.querySelector('input[type="checkbox"]');// 过滤出选中的商品数量数组return check.checked ? +amount.innerText : 0;});console.log(amountArr);// 计算总数量document.querySelector('#sum').innerText = `${numArr.reduce((pre, cur) => pre + cur)}件`;// 计算总金额document.querySelector('#total-amount').textContent = `¥${amountArr.reduce((pre, curr) => pre + curr)}`;}
实现效果:
预览地址:http://easys.ltd/shopcart/
一个模块就是一个独立的js代码块文件,下面将介绍module中的export和import概念。
ES6 module 模块功能使用 export 导出模块的内容,并使用 import 导入模块的内容。
示例:
// math.js(定义模块)exports.add = function(a, b) {return a + b;};// app.js(使用模块)var math = require('./math');var rs = math.add(1, 2);console.log(rs);
创建ES6模块时,可使用export关键字导出(对外提供)模块的内容,如函数、对象以及原始变量等等。
export 导出方案有2种:Named exports(命名导出;每个模块可有多个)和 Default exports(默认导出;每个模块只能一个)。
说明:使用 export + 名称 的形式导出模块的内容。
注意:在 import 导入过程中,需指定这些名称。
// 1) 声明时导出export let myVar = 'a';export const MY_CONST = 'c';export const getName = () => {}...export const getAge = () => {}...export function getName(){return ...}// 2) 声明后导出var myVar = 'a';export const MY_CONST = 'c';const getName = () =>{} ...const getAge = () =>{} ...export {myVar,MY_CONST,getName,getAge}// 3) 别名导出var myVar3 = 'a';export { myVar3 as myVar };// math.jsexport function add(a, b) {return a + b;}// app.js:导入含有命名导出的模块时,需要指定成员名称import { add } from './math.js';console.log(add(1, 2)); // => 3
说明:使用 export default 导出模块默认的内容,每个模块只能有一个 export default。
// 1) 声明时导出 匿名函数export default expression;export default function() {return ...}export default () => {}...// 2) 别名设置为default导出export default function name1() {}export { name1 as default };
默认导出声明的是一个表达式,通常没有名字,导入时需指定模块名称。
// math.jsexport function add(a, b) {return a + b;}export default function cube(x) {return x * x * x;}// app.js:导入默认导出的模块时,需要指定模块名称import cube from './math.js';console.log(cube(3)); // => 27// 若想同时导入含有默认导出、命名导出的模块,只需要导入时用','隔开import cube, { add } from './math.js';
// 1)导入模块的默认导出内容import defaultExport from 'module-name';// 2)导入模块的命名导出内容import { export1, export2 } from 'module-name';import { export as alias } from 'module-name'; // 修改别名import * as name from 'module-name'; // 导入模块内的所有命名导出内容// 3)导入模块的默认导出、命名导出import defaultExport, { export1, export2 } from 'module-name';import defaultExport, * as name from 'module-name';
说明:导入默认导出的模块时,需要指定模块名称
// math.jsexport default function cube(x) {return x * x * x;}// app.js:导入默认导出的模块时,需要指定模块名称import cube from './math.js';console.log(cube(3)); // => 27import user from './default.js' // 如果使用这种引入请导出匿名函数
说明:导入模块时可使用大括号包含指定命名成员;也可以用 * as moduleName 的形式把此模块的所有命名导出作为某个对象的成员。
// math.jsexport function add(a, b) {return a + b;}// app.js:指定使用math模块的add命名导出import { add } from './math.js';console.log(add(1, 2)); // => 3// 按需引入import { getName, getAge } from './utils.js'// 导入所有的命名导出作为math对象的成员import * as math from './math.js';console.log(math.add(1, 2)); // => 3// 将引入的模块赋值到user对象中import * as user from './utils.js'// 结构会变成如下样式// user = {// getAge: function(){ ... }// getName: function(){ ... }// }
说明:仅导入模块时,只会执行模块的全局函数,不会导入任何成员。
// math.jsexport function add(a, b) {return a + b;}function hello() {console.log('hello math.js');}hello();// app.jsimport { add } from './math.js'; // => hello math.js
注意:模块成员在当前使用环境中,既不能重复声明,也不能更新(相对应常量)
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号