DOM- 节点操作

一、节点操作

1、DOM 节点

  • DOM节点: DOM树里每一个内容都称之为节点
  • 节点类型(元素节点最重要,因为需要对他操作)
    • 元素节点
      所有的标签 比如 body、 div
      html 是根节点
    • 属性节点
      所有的属性 比如 href
    • 文本节点
      所有的文本
    • 其他
      在这里插入图片描述

节点可以让我们更好的理清标签元素之间的关系

2、查找节点

  • 关闭二维码案例:
    点击关闭按钮 i, 关闭的是二维码的盒子, 需要获取box盒子
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/8422ef22fa7e4f3c8cf46897b554978d.png
  • 思考:
    关闭按钮 i 和 box 是什么关系呢? 父子关系
     所以,我们完全可以这样做:
    点击关闭按钮, 直接关闭它的爸爸,就无需获取 box 元素了
  • 节点关系:
     父节点
     子节点
     兄弟节点

(1) 父节点查找:

 parentNode 属性,子元素.parentElement 返回的是一个对象
 返回最近一级的父节点 找不到返回为null
在这里插入图片描述

案例–关闭多个二维码案例

需求:多个二维码,点击谁,谁关闭

分析:
①:需要给多个按钮绑定点击事件
②:关闭的是当前的父节点
<!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>Document</title>
    <style>
        .box{
            display: flex;         
        }
        .box img{
            border: 1px solid #000;
        }
        .box i{
            width: 10px;
            height: 10px;
            border: 1px solid #000;
            line-height: 7px;
            text-align: center;
            color: #ccc;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div class="box">   
        <img src="./images/456.png" alt="">
        <i>x</i>
    </div>
    <div class="box">   
        <img src="./images/456.png" alt="">
        <i>x</i>
    </div>
    <div class="box">   
        <img src="./images/456.png" alt="">
        <i>x</i>
    </div>
    <div class="box">   
        <img src="./images/456.png" alt="">
        <i>x</i>
    </div>
    <div class="box">   
        <img src="./images/456.png" alt="">
        <i>x</i>
    </div>    
    <script>
        //获取元素
        let i = document.querySelectorAll('i')
        //绑定事件
        for (let j = 0; j < i.length; j++){
            i[j].addEventListener('click',function(){
                //关闭当前的二维码,点击谁就关闭谁的爸爸
                //没用display='none',这样关掉后不占位,剩下的所有二维码会自动往上移
                //this.parentElement返回的是一个对象
                this.parentElement.style.visibility = 'hidden'
            })
        }
    </script>
</body>
</html>

在这里插入图片描述

注意:
使用visibility = 'hidden'而不是display='none'是因为:
在这里插入图片描述

(2)子节点查找

  • childNodes
    获得所有子节点、包括文本节点(空格、换行)、注释节点等,这些节点获取来没啥用,所以childNodes了解即可
  • children (重点)
    仅获得所有元素节点,返回的是一个伪数组
    在这里插入图片描述
  • 例:点击按钮,让所有孩子变红色
    在这里插入图片描述
<button>点击</button>
<ul>
    <li>孩子1</li>
    <li>孩子2</li>
    <li>孩子3</li>
    <li>孩子4</li>
</ul>
<script>
    // 获取元素
    let btn = document.querySelector('button')
    let ul = document.querySelector('ul')
    //事件监听
    btn.addEventListener('click',function(){
        //通过ul控制所有li,ul.children是伪数组,循环
        for (let i = 0; i<ul.children.length; i++ ){
           ul.children[i].style.color = 'red'
        }
    })
</script>

注意,通过父元素.children 获得的是一个伪数组,想对里面的元素操作都得先遍历或者取出(父元素.children[0])

(3)兄弟节点查找

  • 下一个兄弟节点
    nextElementSibling 属性
  • 上一个兄弟节点
    previousElementSibling 属性
<!-- 兄弟[i+1]变红色 -->
兄弟[i].nextElementSibling.style.color = 'red'

3、增加节点

  • 很多情况下,我们需要在页面中增加元素
     比如,点击发布按钮,可以新增一条信息
    在这里插入图片描述

  • 一般情况下,我们新增节点,按照如下操作:
     创建一个新的节点
     把创建的新的节点放入到指定的元素内部

创建节点

创造出一个新的网页元素,创建元素节点方法:
在这里插入图片描述
注意标签名只能是标签选择器,如div、p等,不能是类选择器或者ID选择器,如果想创建类选择器:

<script>
    let div = document.createElement('div')
    div.className = 'box'
</script>

追加节点

要想在界面看到,还得插入到某个父元素中

  • 插入到父元素的最后一个子元素
    在这里插入图片描述

  • 插入到父元素中某个子元素的前面
    在这里插入图片描述

  • 例:
    在这里插入图片描述

案例–学成在线案例渲染

追加各个小课程
在这里插入图片描述

分析:
①:准备好空的ul 结构
②:根据数据的个数,创建一个新的空li
③:li里面添加内容 img 标题等
④:追加给ul
<!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>Document</title>
    <link rel="stylesheet" href="./index.css">
</head>
<body>  
    <div class="box">
        <div class="head">
            <h3>精品推荐</h3>
            <p>查看全部</p>
        </div> 
        <div class="body">
            <ul>
            <!-- 开始是空的,一个li也没有,后面在script里面追加,实现html个js分离 -->
            </ul>
        </div>
    </div>
    
    <script>
        let data = [
                        {
                            src: 'images/course01.png',
                            title: 'Think PHP 5.0 博客系统实战项目演练',
                            num: 1125
                        },
                        {
                            src: 'images/course02.png',
                            title: 'Android 网络动态图片加载实战',
                            num: 357
                        },
                        {
                            src: 'images/course03.png',
                            title: 'Angular2 大前端商城实战项目演练',
                            num: 22250
                        },
                        {
                            src: 'images/course04.png',
                            title: 'Android APP 实战项目演练',
                            num: 389
                        },
                        {
                            src: 'images/course05.png',
                            title: 'UGUI 源码深度分析案例',
                            num: 124
                        },
                        {
                            src: 'images/course06.png',
                            title: 'Kami2首页界面切换效果实战演练',
                            num: 432
                        },
                        {
                            src: 'images/course07.png',
                            title: 'UNITY 从入门到精通实战案例',
                            num: 888
                        },
                        {
                            src: 'images/course08.png',
                            title: 'Cocos 深度学习你不会错过的实战',
                            num: 590
                        }                   
                       
                    ]   
        //获取元素
        let ul = document.querySelector('ul')
        for(let i = 0; i<data.length;i++){
            //根据数据的个数,创建li
            let li = document.createElement('li')
            //li添加内容
            li.innerHTML = `
                <img src="${data[i].src}" alt=""></img>
                <h4>${data[i].title}</h4>
                <div class="info">
                <span>高级</span> • 
                <span>${data[i].num}</span>人在学习
                </div> `
            //追加给ul
            ul.appendChild(li)
        }
    </script>
</body>
</html>

原本是将<script>写到 ul 里面实现数据渲染的,现在可以通过追加实现 html 和 js 分离

4、克隆节点

特殊情况下,我们新增节点,按照如下操作:
 复制一个原有的节点
 把复制的节点放入到指定的元素内部

  • 克隆节点
    在这里插入图片描述
    cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值
     若为true,则代表克隆时会包含后代节点一起克隆
     若为false,则代表克隆时不包含后代节点
     默认为false

克隆与新建节点一样,需要配合追加节点操作,否则结构中还是不会有此节点

在这里插入图片描述

5、删除节点

若一个节点在页面中已不需要时,可以删除它
在 JavaScript 原生DOM操作中,要删除元素必须通过父元素删除

  • 语法:
    在这里插入图片描述

如不存在父子关系则删除不成功
删除节点和隐藏节点(display:none) 有区别的: 隐藏节点还是存在的,但是删除,则从html中删除节点

在这里插入图片描述

二、时间对象

  • 时间对象:用来表示时间的对象
  • 作用:可以得到当前系统时间

1、实例化

  • 代码中 new 关键字,一般将这个操作称为实例化
  • 在代码中发现了 new 关键字时,一般将这个操作称为实例化
    在这里插入图片描述

2、时间对象方法

因为时间对象返回的数据我们不能直接使用,所以需要转换为实际开发中常用的格式
在这里插入图片描述

案例–页面显示时间

需求:将当前时间以:YYYY-MM-DD HH:mm 形式显示在页面

<!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>Document</title>
    <style>
        div{
            width: 300px;
            height: 50px;
        }
    </style>
</head>
<body>
    <div></div>
    <script>
        setInterval(function(){
            //new时间对象
            //小括号为空可以得到当前时间
            let date = new Date()
            let year = date.getFullYear()
            let month = date.getMonth()+1
            let day = date.getDate()
            let hour = date.getHours()
            let min = date.getMinutes()
            let sec = date.getSeconds()
            let div = document.querySelector('div')
            div.innerHTML = `${year}-${month}-${day} ${hour}:${min}:${sec}`
        },1000)
    </script>
</body>
</html>

在这里插入图片描述

3、时间戳

  • 时间戳概念
    是指1970年01月01日00时00分00秒起至现在的毫秒数,它是一种特殊的计量时间的方式
    可以用来倒计时,我们无法直接用将来的时间减去现在的时间,但是将来的时间有时间戳,现在的时间也有时间戳,时间戳可以做差然后转换为小时:分钟:秒,就可以倒计时。
  • 三种方式获取时间戳
    • 使用 getTime() 方法
      在这里插入图片描述
    • 简写 +new Date(),+是正号
      在这里插入图片描述
    • 使用 Date.now()
      在这里插入图片描述
      无需实例化
      但是只能得到当前的时间戳, 而前面两种可以返回指定时间的时间戳

下课倒计时效果

需求:计算到下课还有多少时间

分析:
①:用将来时间减去现在时间就是剩余的时间
②:核心: 使用将来的时间戳减去现在的时间戳
③:把剩余的时间转换为 天 时 分 秒
注意:
1. 通过时间戳得到是毫秒,需要转换为秒在计算
2. 转换公式:
 d = parseInt(总秒数 /60/60 /24); // 计算天数
 h = parseInt(总秒数 /60/60 %24) // 计算小时
 m = parseInt(总秒数 /60 %60 ); // 计算分数
 s = parseInt(总秒数%60); // 计算当前秒数
<!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>Document</title>
  <style>
    .countdown {
      width: 240px;
      height: 305px;
      text-align: center;
      line-height: 1;
      color: #fff;
      background-color: brown;
      /* background-size: 240px; */
      /* float: left; */
      overflow: hidden;
    }
    .countdown .next {
      font-size: 16px;
      margin: 25px 0 14px;
    }
    .countdown .title {
      font-size: 33px;
    }
    .countdown .tips {
      margin-top: 80px;
      font-size: 23px;
    }
    .countdown small {
      font-size: 17px;
    }
    .countdown .clock {
      width: 142px;
      margin: 18px auto 0;
      overflow: hidden;
    }
    .countdown .clock span,
    .countdown .clock i {
      display: block;
      text-align: center;
      line-height: 34px;
      font-size: 23px;
      float: left;
    }
    .countdown .clock span {
      width: 34px;
      height: 34px;
      border-radius: 2px;
      background-color: #303430;
    }
    .countdown .clock i {
      width: 20px;
      font-style: normal;
    }
  </style>
</head>

<body>
    <div class="countdown">
        <p class="next">今天是</p>
        <p class="title">下班倒计时</p>
        <p class="clock">
            <span id="hour">00</span>
            <i>:</i>
            <span id="minutes">25</span>
            <i>:</i>
            <span id="second">20</span>
        </p>
        <p class="tips">现在是</p>
    </div>
    <script>
      //下班倒计时
        //获取元素
        let h = document.querySelector('#hour')
        let m = document.querySelector('#minutes')
        let s = document.querySelector('#second')
        //先调用一下,因为定时器会有一秒空白期,先调用可以避免
        time()
        setInterval(time,1000)
        function time(){         
            //现在的时间戳
            let now = +new Date()
            //指定时间的时间戳
            let fu = +new Date('2022-7-19 24:00:00')
            //计算时间戳差值,转换为s
            let count = (fu-now) / 1000
            //转换为时分秒
            let hour = parseInt (count/60/60%24)
            hour = hour < 10 ? '0'+ hour:hour
            let min = parseInt (count/60%60)
            min = min < 10 ? '0'+ min:min
            let sec = parseInt (count%60)
            sec = sec < 10 ? '0'+ sec:sec
            //写入时间
            h.innerHTML = hour
            m.innerHTML = min
            s.innerHTML = sec
        }  
    </script>
</body>
</html>

在这里插入图片描述

三、综合案例–发布微博

需求1
注册input事件
将文本的内容的长度赋值给对应的数值
表单的maxlength属性可以直接限制在200个数之间

需求2
判断如果内容为空,则提示不能输入为空, 并且直接return
防止输入无意义空格, 使用字符串.trim()去掉首尾空格, 并将表单的value值设置为空字符串
        
需求3
获取文本域的内容, 赋值给新标签里面的text.value
随机获取数据数组里面的内容, 替换新建立节点的图片和名称
利用时间对象将时间动态化 new Date().toLocaleString()

需求4
在事件处理函数里面获取点击按钮,注册点击事件,删除评论,
放到追加进ul的前面,这样创建元素的同时顺便绑定了删除事件,不用后面再循环绑定很麻烦
(易错点: 必须在事件里面获取,外面获取不到,因为只有发布了的才能被删除)
删除对应的元素

需求5
将表单域内容重置为空
将use里面的内容重置为0
<!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>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        ul {
            list-style: none;
        }

        /* 文本框 */
        .wei {
            width: 900px;
            margin: 0 auto;

        }

        .wei textarea {
            width: 900px;
            height: 112px;
            resize: none;
            border-radius: 10px;
            outline: none;
            padding-top: 10px;
            padding-left: 20px;
            font-size: 18px;
        }

        /* 底部字数按钮 */
        .wei .bottom {
            float: right;
        }

        .wei span {
            color: #666;
        }

        .wei .use {
            color: red;
        }

        .wei button {
            width: 100px;
            height: 30px;
            background-color: rgb(0, 132, 255);
            border: 0;
            line-height: 30px;
            text-align: center;
            color: #fff;
            font: bold 14px '宋体';
            cursor: pointer;
        }

        button:hover {
            background: rgb(0, 225, 255);
        }

        /* 微博内容发布列表 */
        ul {
            margin-top: 80px;
        }

        ul li {
            position: relative;
            padding: 20px 0;
            border-bottom: 1px dashed #ccc;
        }

        /* 头像昵称发布时间 */
        ul li .info {
            position: relative;
        }

        ul li .info .userpic {
            width: 80px;
            height: 80px;
            border-radius: 50%;
        }

        ul li .info .username {
            position: absolute;
            top: 15px;
            left: 100px;
            font: bold 16px '宋体';
        }

        ul li .info .sendtime {
            position: absolute;
            top: 40px;
            left: 100px;
            color: #aaa;
            font-size: 12px;
        }

        /* 发布内容  */
        ul li .content {
            padding-left: 100px;
            color: #666;
        }

        /* x删除评论 */
        ul li .del {
            position: absolute;
            top: 0;
            right: 0;
            font-size: 28px;
            cursor: pointer;
        }
    </style>
</head>

<body>
    <div class="wei">
        <img src="./images/9.6/tip.png" alt="">
        <br>
        <!-- maxlength控制最大输入长度 -->
        <textarea placeholder="说点什么吧..." id="area" cols="30" rows="10" maxlength="200"></textarea>
        <div class="bottom">
            <span class="use">0</span>
            <span>/</span>
            <span>200</span>
            <button>发布</button>
        </div>

        <!-- 微博内容发布列表 -->
        <div>
            <ul>
                <!-- 等js新建节点追加 -->

            </ul>
        </div>
    </div>

    <script>
        // 模拟数据
        let dataArr = [
            { uname: '司马懿', imgSrc: './images/9.5/01.jpg' },
            { uname: '女娲', imgSrc: './images/9.5/02.jpg' },
            { uname: '百里守约', imgSrc: './images/9.5/03.jpg' },
            { uname: '亚瑟', imgSrc: './images/9.5/04.jpg' },
            { uname: '虞姬', imgSrc: './images/9.5/05.jpg' },
            { uname: '张良', imgSrc: './images/9.5/06.jpg' },
            { uname: '安其拉', imgSrc: './images/9.5/07.jpg' },
            { uname: '李白', imgSrc: './images/9.5/08.jpg' },
            { uname: '阿珂', imgSrc: './images/9.5/09.jpg' },
            { uname: '墨子', imgSrc: './images/9.5/10.jpg' },
            { uname: '鲁班', imgSrc: './images/9.5/11.jpg' },
            { uname: '嬴政', imgSrc: './images/9.5/12.jpg' },
            { uname: '孙膑', imgSrc: './images/9.5/13.jpg' },
            { uname: '周瑜', imgSrc: './images/9.5/14.jpg' },
            { uname: '老夫子', imgSrc: './images/9.5/15.jpg' },
            { uname: '狄仁杰', imgSrc: './images/9.5/16.jpg' },
            { uname: '扁鹊', imgSrc: './images/9.5/17.jpg' },
            { uname: '马可波罗', imgSrc: './images/9.5/18.jpg' },
            { uname: '露娜', imgSrc: './images/9.5/19.jpg' },
            { uname: '孙悟空', imgSrc: './images/9.5/20.jpg' },
            { uname: '黄忠', imgSrc: './images/9.5/21.jpg' },
            { uname: '百里玄策', imgSrc: './images/9.5/22.jpg' },
        ]
        // 需求1
        // 注册input事件
        // 将文本的内容的长度赋值给对应的数值
        // 表单的maxlength属性可以直接限制在200个数之间

        // 获取元素
        let text = document.querySelector('textarea')
        let use = document.querySelector('.use')
        // 事件监听,输入出发监听
        text.addEventListener('input', function () {
            //不断获得文本框的字符长度,表单数据获取需要通过元素的value获取,而对于div则需要通过innerHTML获取
            use.innerHTML = text.value.length
        })

        // 需求2
        // 判断如果内容为空,则提示不能输入为空, 并且直接return
        // 防止输入无意义空格, 使用字符串.trim()去掉首尾空格, 并将表单的value值设置为空字符串

        //获取元素
        let btn = document.querySelector('button')
        btn.addEventListener('click', function () {
            if (text.value.trim() === '') {
                text.value = ''
                use.innerHTML = 0
                return alert('内容不能为空')
            }
            // 需求3
            // 获取文本域的内容, 赋值给新标签里面的text.value
            // 随机获取数据数组里面的内容, 替换新建立节点的图片和名称
            // 利用时间对象将时间动态化 new Date().toLocaleString()
            function getRandom(min, max) {
                return Math.floor(Math.random() * (max - min + 1) + min)
            }
            let random = getRandom(0, dataArr.length - 1)
            let ul = document.querySelector('ul')
            let li = document.createElement('li')
            li.innerHTML = `<!-- 头像昵称发布时间 -->
                    <div class="info">
                        <img class="userpic" src=${dataArr[random].imgSrc} alt="">
                        <span class="username">${dataArr[random].uname}</span>
                        <span class="sendtime">${new Date().toLocaleString()}</span>
                    </div>
                    <!-- 发布内容 -->
                    <div class="content">${text.value}</div>
                    <!-- X -->
                    <div class="del">X</div>
            `
            // 需求4
            // 在事件处理函数里面获取点击按钮, 注册点击事件
            //     (易错点: 必须在事件里面获取, 外面获取不到)
            // 删除对应的元素
            // 因为li只新建还没追加,在document里面找不到,所以在li里面找
            let del = li.querySelector('.del')
            del.addEventListener('click',function(){
                ul.removeChild(li)
            })
            ul.insertBefore(li, ul.children[0])

            // 需求5
            // 将表单域内容重置为空
            // 将use里面的内容重置为0
            text.value = ''
            use.innerHTML = 0
        })
    </script>
</body>

</html>

在这里插入图片描述

四、重绘和回流

1、 浏览器是如何进行界面渲染的

在这里插入图片描述
 解析(Parser)HTML,生成DOM树(DOM Tree)
 同时解析(Parser) CSS,生成样式规则 (Style Rules)
 根据DOM树和样式规则,生成渲染树(Render Tree)
 进行布局 Layout(回流/重排):根据生成的渲染树,得到节点的几何信息(位置,大小)
 进行绘制 Painting(重绘): 根据计算和获取的信息进行整个页面的绘制
 Display: 展示在页面上

2、 重绘和回流(重排)

  • 回流(重排)
    当 Render Tree 中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或全部文档的过程称为回流。

  • 重绘
    由于节点(元素)的样式的改变并不影响它在文档流中的位置和文档布局时(比如:color、background-color、outline等), 称为重绘。

  • 重绘不一定引起回流,而回流一定会引起重绘

  • 会导致回流(重排)的操作:
     页面的首次刷新
     浏览器的窗口大小发生改变
     元素的大小或位置发生改变
     改变字体的大小
     内容的变化(如:input框的输入,图片的大小)
     激活css伪类 (如::hover)
     脚本操作DOM(添加或者删除可见的DOM元素)
    简单理解,影响到布局了,就会有回流
    在这里插入图片描述

五、购物车案例

需求:能够实现商品数量加减、删除,以及总价和总数的计算
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>购物车全选功能</title>
    <!-- 引入初始化 -->
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        ul {
            list-style: none;
        }

        a {
            text-decoration: none;
            color: #666;
        }

        body {
            background: #fff;
            color: #666;
            font-size: 14px;
        }

        input {
            outline: none;
        }

        .clearfix::before,
        .clearfix::after {
            content: '';
            display: block;
            clear: both;
        }

        .clearfix {
            *zoom: 1;
        }
    </style>
    <!-- 引入购物车样式 -->
    <style>
        table {
            width: 800px;
            margin: 0 auto;
            border-collapse: collapse;
        }

        th {
            font: normal 14px/50px '宋体';
            color: #666;
        }

        th,
        td {
            border: none;
            text-align: center;
            border-bottom: 1px dashed #ccc;
        }

        input[type='checkbox'] {
            width: 13px;
            height: 13px;
        }

        tbody p {
            position: relative;
            bottom: 10px;
        }

        tbody .add,
        tbody .reduce {
            float: left;
            width: 22px;
            height: 22px;
            border: 1px solid #ccc;
            text-align: center;
            background: none;
            outline: none;
            cursor: pointer;
        }

        tbody input[type='text'] {
            width: 50px;
            float: left;
            height: 18px;
            text-align: center;
        }

        tbody .count-c {
            width: 98px;
            margin: 0 auto;
        }

        button[disabled] {
            color: #ddd;
            cursor: not-allowed;
        }

        tbody tr:hover {
            background: #eee;
        }

        tbody tr.active {
            background: rgba(241, 209, 149, 0.945);
        }

        .controls {
            width: 790px;
            margin: 10px auto;
            border: 1px solid #ccc;
            line-height: 50px;
            padding-left: 10px;
            position: relative;
        }

        .controls .del-all,
        .controls .clear {
            float: left;
            margin-right: 50px;
        }

        .controls p {
            float: right;
            margin-right: 100px;
        }

        .controls span {
            color: red;
        }

        .controls .pay {
            position: absolute;
            right: 0;
            width: 80px;
            height: 54px;
            background: red;
            font: bold 20px/54px '宋体';
            color: #fff;
            text-align: center;
            bottom: -1px;
        }

        .controls .total-price {
            font-weight: bold;
        }
    </style>
</head>

<body>
    <div class="car">
        <table>
            <thead>
                <tr>
                    <th><input type="checkbox" id="all" />全选</th>
                    <th>商品</th>
                    <th>单价</th>
                    <th>商品数量</th>
                    <th>小计</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody id="carBody">
                <tr>
                    <td>
                        <input class="s_ck" type="checkbox" readonly />
                    </td>
                    <td>
                        <img src="./images/01.jpg" />
                        <p>牛奶</p>
                    </td>
                    <td class="price">5¥</td>
                    <td>
                        <div class="count-c clearfix">
                            <button class="reduce" disabled>-</button>
                            <input type="text" value="1" />
                            <button class="add">+</button>
                        </div>
                    </td>
                    <td class="total">5¥</td>
                    <td>
                        <a href="javascript:" class="del">删除</a>
                    </td>
                </tr>
                <tr>
                    <td>
                        <input class="s_ck" type="checkbox" />
                    </td>
                    <td>
                        <img src="./images/01.jpg" />
                        <p>牛奶</p>
                    </td>
                    <td class="price">10¥</td>
                    <td>
                        <div class="count-c clearfix">
                            <button class="reduce" disabled>-</button>
                            <input type="text" value="1" />
                            <button class="add">+</button>
                        </div>
                    </td>
                    <td class="total">10¥</td>
                    <td>
                        <a href="javascript:" class="del">删除</a>
                    </td>
                </tr>
                <tr>
                    <td>
                        <input class="s_ck" type="checkbox" />
                    </td>
                    <td>
                        <img src="./images/01.jpg" />
                        <p>牛奶</p>
                    </td>
                    <td class="price">20¥</td>
                    <td>
                        <div class="count-c clearfix">
                            <button class="reduce" disabled>-</button>
                            <input type="text" value="1" />
                            <button class="add">+</button>
                        </div>
                    </td>
                    <td class="total">20¥</td>
                    <td>
                        <a href="javascript:" class="del">删除</a>
                    </td>
                </tr>
                <tr>
                    <td>
                        <input class="s_ck" type="checkbox" />
                    </td>
                    <td>
                        <img src="./images/01.jpg" />
                        <p>牛奶</p>
                    </td>
                    <td class="price">35¥</td>
                    <td>
                        <div class="count-c clearfix">
                            <button class="reduce" disabled>-</button>
                            <input type="text" value="1" />
                            <button class="add">+</button>
                        </div>
                    </td>
                    <td class="total">35¥</td>
                    <td>
                        <a href="javascript:" class="del">删除</a>
                    </td>
                </tr>
            </tbody>
        </table>
        <div class="controls clearfix">
            <a href="javascript:" class="del-all">删除所选商品</a>
            <a href="javascript:" class="clear">清理购物车</a>
            <a href="javascript:" class="pay">去结算</a>
            <p>
                已经选中<span id="totalCount">4</span>件商品;总价:<span id="totalPrice" class="total-price">0¥</span>
            </p>
        </div>
    </div>
    <script>
        // + - 删除是相同的,一一对应的 可以用一个for来遍历绑定事件
        //加
        let add = document.querySelectorAll('.add')
        //减
        let reduce = document.querySelectorAll('.reduce')
        //删除
        let del = document.querySelectorAll('.del')
        //每个商品个数
        let input = document.querySelectorAll('.count-c input')
        //单价
        let price = document.querySelectorAll('.price')
        //每个商品总价
        let total = document.querySelectorAll('.total')
        //商品盒子
        let carBody = document.querySelector('#carBody')
        //总共商品数
        let goods = document.querySelector('#totalCount')
        //总价
        let money = document.querySelector('#totalPrice')
        for (let i = 0; i < add.length; i++) {
            //1、加号
            add[i].addEventListener('click', function () {
                input[i].value++
                reduce[i].disabled = false
                total[i].innerHTML = parseInt(price[i].innerHTML) * input[i].value + '¥'
                result()
            })
            //2、减号
            reduce[i].addEventListener('click', function () {
                input[i].value--
                if (input[i].value <= 1) {
                    reduce[i].disabled = true
                }
                total[i].innerHTML = parseInt(price[i].innerHTML) * input[i].value + '¥'
                result()
            })
            //3、删除
            del[i].addEventListener('click', function () {
                //没办法用carBody.removeChild(carBody.children[i]),例如第一次点击删除1想删除1号商品
                // 第二次想点击删除2的删除2号商品但这个时候商品2是父节点的第一个孩子
                carBody.removeChild(this.parentNode.parentNode)
                result()
            })
        }

        function result() {
            let sum = 0
            let num = 0
            //删除后,需要重新获取每个商品个数和总价,否则还是删除之前的数,如删除1号商品后,
            //对2号商品操作会显示在3号商品,因为此时3号商品才是第二个孩子
        
            //每个商品个数
            let input = document.querySelectorAll('.count-c input')
            //每个商品总价
            let total = document.querySelectorAll('.total')
            for (let i = 0; i < total.length; i++) {
                sum += +parseInt(total[i].innerHTML)
                num += +input[i].value
            }
            goods.innerHTML = num
            money.innerHTML = sum + '¥'
        }
        // div  span   ul  li  标签  有文字内容  怎么得到或则设置文字内容呢  元素.innerText   元素.innerHTML
        // 表单  input 单选 复选    textarea  select  怎么得到或则设置值   表单的value
        // 特殊的  button 是通过inner来设置
    </script>
</body>
</html>

在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值