基于传统操作dom的方式实现计算器(html+js笔记)

效果图:css此处自行设计。

html:

<div class="box" id="ComputedBox">
    <div class="top">
        <div class="hang">
    <!-- i标签显示斜体文本效果。minus和add是自定义类名,用于控制按钮的样式。-->
            <i class="minus"> </i>
            <span class="pronum">2</span>
            <i class="add"> </i>
          <span class="info">
            单价:12.5元&nbsp;&nbsp;
            小计:<em>0</em>元
            </span>
        </div> 
    </div>
    <!-- 底部显示商品合计件数和总价 -->
    <div class="bottom">
        商品合计:<span class="pronum">0</span>&nbsp;件
        <br>
        共花费了:<span class="pronum">0</span>&nbsp;元
    </div>
</div>

取出数据:

// 想操作哪些DOM,就要先获取这些元素
let computedBox = document.querySelector('#computedBox'),
// 获取整个计算器元素,document.querySelector可以获取文档中的第一个匹配的元素。
    topBox = computedBox.querySelectorAll('.top'),
    // 获取顶部元素,querySelectorAll可以获取文档中所有top元素的集合。
    [totolCountBox,totolPriceBox] = Array.from(computedBox.querySelectorAll('.bottom span')),
    // 获取底部盒子元素并用array.from将其转换为商品合计和总计元素的数组。
    // Array.from() 是 ES6 中新增方法,它可以从类数组对象或可迭代对象(如字符串、Set、Map、NodeList 等)创建一个新的数组实例。
    countsBox=[],
    subtotalBox=[];
    // 定义数组,用于存储各项商品的数量和小计。

取出dom元素以后,我们就可以进行动态绑定啦:

    // ‌具名函数表达式binding()
    // 在JavaScript中,具名函数表达式允许在函数表达式中给函数本身命名,而不是仅仅将函数赋值给一个变量。
    const binding = function binding() {
        let str='';
        // 定义一个字符串变量,用于存储商品信息。
        data.forEach(item,index => {
            // forEach 用于遍历data数组,获取每一项商品的数量和价格。
            let {count,price} = item;
            // 解构赋值,获取每一项商品的数量和价格。
             str += `<div class="hang">
            <i class="minus"></i>
            <span class="pronum">${count}</span>
            <i class="add"></i>
          <span class="info">
            单价:${price}元&nbsp;&nbsp;
            小计:<em>${count*price}</em>元
            </span>
        </div> `;
        // 新增每一项商品的HTML代码。
        });
        topBox.innerHTML = str;
        // 将当前商品信息填充到顶部元素中。
        countsBox = Array.from(topBox.querySelectorAll('span.pronum'));
        // 把底部数据元素转换为数组,用于计算商品个数和总费用。
        subtotalBox = Array.from(topBox.querySelectorAll('em'));
        // 得到每项商品的小计元素的集合,用于计算总费用。
    };
    binding();
    // 调用binding()函数,初始化计算器。

动态绑定后便可以计算总计信息:

    const computed = function computed() {
        let counts = 0;
            prices = 0;
        // 定义两个变量,用于存储商品的数量和价格。
        countsBox.forEach(_,index => {
            // forEach 遍历商品数量元素,获取每一项商品的数量。
            // +bindBox[index].innerHTML 将字符串转换为数字。或者用Number()函数也行。
            counts += +countsBox[index].innerHTML;
            // 累加商品数量得到总数量。
            prices += +subtotalBox[index].innerHTML;
            // 累加商品小计得到总费用。
        });
        totolCountBox.innerHTML = counts;
        // 更新商品总数。
        totolPriceBox.innerHTML = prices;
        // 更新商品总费用。
    };
    // 定义计算器函数。

此时可以修改绑定函数:

subtotalBox = Array.from(topBox.querySelectorAll('em'));
        // 得到每项商品的小计元素的集合,用于计算总费用。
        computed();
        // 计算一下总费用。
    };
    binding();

函数也写好,我们就可以基于事件委托实现点击事件绑定啦:

注意:在元素上写事件和addEventListener()的区别?

  1. onclick添加事件不能绑定多个事件,后面绑定的会覆盖前面的。而addEventListener能添加多个事件绑定,按顺序执行。
  2. onclick只能冒泡,addEventListener()可以得到捕获or冒泡。
  3. addEventListener方式,不支持低版本的IE。(attachEvent 支持IE)。
  4. 普通方式绑定事件后,不可以取消。addEventListener绑定后则可以用 removeEvenListener 取消。
topBox.addEventListener ('click',function(ev) {
        // addEventListener() 方法用于向指定元素添加一个或多个事件监听器。
        // 监听顶部元素的点击事件。
        let target = ev.target;
            targetTag= target.tagName;
        // 获取点击的元素的标签名。
            targetSty = target.className;
        // 获取点击的元素的类名。

        if(targetTag !== 'I' )return;
        // 如果点击的不是i标签,即不是加号或减号,则直接返回。
        let parent = target.parentNode;
            index = +parent.getAttribute('index');
        // 获取点击的元素的索引值。
            price = data[index].price,
            itemCountBox = countsBox[index],
            itemSubtotalBox = subtotalBox[index];
        // 获取当前点击的商品的价格和数量元素。
        if(targetSty ==='minus'){
            // 如果点击的是减号,则减少商品数量。
            itemCountBox.innerHTML--;
            if(+itemCountBox.innerHTML < 0){
                itemCountBox.innerHTML = 0;
            }
        }else{
            itemCountBox.innerHTML++;
        }
        itemSubtotalBox.innerHTML = itemCountBox.innerHTML;
        // 更新商品数量。
        computed();
        // 计算总费用。
    });
    // 监听顶部元素的点击事件,并执行相应的操作。

在此补充一点:es6箭头函数。

// 箭头函数,单个元素括号可省略
let fn = (name) => {
    // 函数体
    return `Hello ${name} !`;
};

// 等同于
let fn = function (name) {
    // 函数体
    return `Hello ${name} !`;
};

详细链接:ES6箭头函数详解-优快云博客

完结撒花~~

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值