DOM

DOM 树

获取DOM元素

  • 非常规标签
    • html/head/body
      • document.documentElement
      • document.head
      • document.body
  • 常规标签
    • 能用常规标签的方法去获取非常规标签,知识一般不这样用
  • getElementById()
    • 语法:查找范围.getElementById(‘id名称’)
    • 返回值:
      • 元素
      • 或者null
  • getElementsByTagName()
    • 语法:查找范围.getElementsByTagName(‘标签名’)
    • 返回值
      • 所有范围内这个标签名组成的一个伪数组
      • 或者空的伪数组
  • getElementsByClassName()
    • 语法:查找范围.getElementsByClassName(‘类名’)
    • 返回值
      • 所有范围内这个组成的一个伪数组
      • 或者空的伪数组
  • getElementsByName()
    • 语法:查找范围.getElementsByName(‘元素name属性的值’)
    • 返回值
      • 所有范围内这个元素name属性的值组成的一个伪数组
      • 或者空的伪数组
  • querySelector()
    • 语法:查找范围.querySelector(‘选择器’)
    • 返回值
      • 如果找到选择器匹配的内容,则返回第一个
      • null
    • IE低版本不支持
  • querySelectorAll()
    • 语法:查找范围.querySelectorAll(‘选择器’)
    • 返回值
      • 如果找到选择器匹配的元素,则返回全部
      • 空的伪数组
    • IE低版本不支持

元素的属性

  • 什么是元素的属性
  • 原生属性
    • id/class/style/type/src/…
  • 自定义属性
    • aaa/abc/hhhh/…
  • H5 自定义属性
    • data-*
  • 操作标签上的三种属性
  • 原生属性
    • 元素.属性名(class)除外,类名用 元素.className
    • 增删查改
      • 增/改 元素.属性名 = ‘值’
      • 查 元素.属性名
  • 自定义属性
    • 不能直接点操作
    • 增删查改
      • 增/改 元素.setAttribute(‘属性名’,‘属性值’)
      • 删 removeAttribute(‘属性名’)
      • 查 getAttribute(‘属性名’) // 拿到的时候都是字符串
    • 可以操作自定义属性,也可以操作原生属性(一般不这么用)
  • H5 自定义属性
    • 每一个元素身上有一个属性叫做dataset
    • 里面包含了所有 H5 自定义属性
      • key 是除了 data- 以外的部分
      • value 就是这个属性的值
    • 增删查改
      • 增/改 元素.dataset.key = ‘value’
      • 删 delete 元素.dataset.key
      • 查 元素.dataset.key

操作元素类名

  • 设置类名
    • 设置/改 元素.className = ‘className’
    • 追加类名 元素.className += ' secondClassName'
    • 删除类名(好加不好去)
      • 获取类名
      • 截取字符串
      • 按照空格切开,循环便利,找到想删除的那个
      • 再写一遍
  • H5 标准提供的API
    • classList 元素.classList
      1. add()
      • 元素.classList.add(‘你要添加的类名’)
      1. remove()
      • 元素.classList.remove(‘你要移除的类名’)
      1. toggle()
      • 元素.classList.toggle(‘你要切换的类名’)
      • 如果有就删除,如果没有就添加(开关)

操作文本内容

  • innerHTML
    • 读写的属性
      • 操作元素的超文本内容
      • 读:获取元素内部所有的内容
        • 文本+标签全部内容
        • 以字符串的形式范围
        • 语法:元素.innerHTML
      • 写:设置元素内部所有的内容
        • 完全覆盖的书写
        • 语法:元素.innerHTML = ‘你要设置的内容’
        • 出现 HTML 结构时会自动解析
  • innerText
    • 一个读写的属性
    • 操作元素的文本内容
      • 读:获取元素内部的所有文本内容
        • 包括子元素后代元素里的文本内容
        • 标签内容不获取
        • 语法:元素.innerText
      • 写:设置元素内部的文本内容
        • 完全覆盖式的写
        • 语法:元素.innerText = ‘你要设置的内容’
        • 出现 HTML 结构时不会自动解析
  • value
    • 一个读写的属性
    • 操作表单的元素的 value 值
    • 读:获取表单元素的 value 值
      • 语法:元素.value
    • 写:设置表单元素的 value 值
      • 语法:元素.value = ‘你要设置的值’

全选

<style>
    *{
        margin: 0;
        padding: 0;
    }

    .box {
        width:160px;
        padding: 5px;
        border: 1px solid #333;
        margin: 100px auto;
    }

    .box >div{
        padding: 15px;
    }
</style>

<body>
    <div class="box">
        <div class="all">
            全选:<input type="checkbox" name="" id="">
        </div>
        <hr/>
        <div class="items">
            选项1: <input type="checkbox"> <br/> 选项2: 
            <input type="checkbox"> <br/> 选项3: 
            <input type="checkbox"><br/> 选项4:
            <input type="checkbox"><br/> 选项5:
            <input type="checkbox"><br/>
        </div>
    </div>
</body>

<script>
    let allBtn = document.querySelector('.all > input');
    let itemsBtns = document.querySelectorAll('.items > input');

    // 给 allTtn 绑定点击事件
    allBtn.onclick = function() {
            // 获取自己当前的状态
            let type = allBtn.checked;

            // 遍历循环 itemBtns
            // for (let i = 0; i < itemsBtns.length; i++) {
            //     itemsBtns[i].checked = type;
            // }
            // 或者
            itemsBtns.forEach(function(item) {
                item.checked = type;
            });
        }
        // 给每一个选项按钮添加点击事件
    itemsBtns.forEach(function(item) {
        item.onclick = function() {
            // 判断是不是每一个都选中
            let flag = true;
            itemsBtns.forEach(function(item) {
                if (!item.checked) flag = false;
            })
            console.log(flag);
            allBtn.checked = flag;
        }
    });
</script>

选项卡

<style>
    * {
        margin: 0;
        padding: 0;
    }
    
    ul,
    ol,
    li {
        list-style: none;
    }
    
    .box {
        width: 600px;
        height: 400px;
        border: 10px solid #3e3e3e;
        margin: 50px auto;
        /* overflow: hidden; */
    }
    
    .box>ul {
        height: 50px;
        width: 100%;
        overflow: hidden;
    }
    
    .box>ul>li {
        float: left;
        width: 200px;
        height: 100%;
        text-align: center;
        line-height: 50px;
        font-size: 30px;
        background-color: skyblue;
        color: #fff;
        cursor: pointer;
    }
    
    .box>ul>li.active {
        background-color: orange;
    }
    
    .box>ol {
        width: 100%;
        height: 350px;
        position: relative;
    }
    
    .box>ol>li {
        width: 100%;
        height: 100%;
        background-color: purple;
        text-align: center;
        line-height: 350px;
        font-size: 100px;
        color: #fff;
        position: absolute;
        left: 0;
        top: 0;
        display: none;
    }
    
    .box>ol>li.active {
        display: block;
    }
</style>

<body>
    <div class="box">
        <ul>
            <li class="active">1</li>
            <li>2</li>
            <li>3</li>
        </ul>
        <ol>
            <li class="active">1</li>
            <li>2</li>
            <li>3</li>
        </ol>
    </div>
</body>

<script>
    let btns = document.querySelectorAll('ul > li');
    let tabs = document.querySelectorAll('ol > li');

    btns.forEach(function(item, index) {

        item.onclick = function() {
            btns.forEach(function(b, i) {
                b.className = '';
                tabs[i].className = '';
            })
            item.className = 'active';
            tabs[index].className = 'active';
        }
    });
</script>

返回顶部

<style>
        * {
            margin: 0;
            padding: 0;
        }
        
        body {
            height: 3000px;
        }
        
        .topBar {
            width: 100%;
            height: 50px;
            line-height: 50px;
            text-align: center;
            color: #fff;
            background-color: skyblue;
            position: fixed;
            font-size: 30px;
            left: 0;
            top: 0;
            display: none;
        }
        
        .topBar.active {
            display: block;
            transition: 1s ease-in-out;
        }
        
        .goTop {
            width: 50px;
            height: 50px;
            line-height: 25px;
            font-size: 20px;
            color: #fff;
            background-color: pink;
            position: fixed;
            bottom: 50px;
            right: 50px;
            text-align: center;
            display: none;
        }
        
        .goTop.active {
            display: block;
        }
    </style>
</head>

<body>
    <div class="topBar">顶部</div>
    <div class="goTop">回到顶部</div>
    <script>
        let topBar = document.querySelector('.topBar');
        let goTop = document.querySelector('.goTop');
        window.onscroll = function() {

            let scollTop = document.documentElement.scrollTop || document.body.scrollTop;
            if (scollTop >= 300) {
                // topBar.className = 'topBar active';
                // goTop.className = 'goTop active';
                topBar.classList.add('active');
                goTop.classList.add('active');
            } else {
                // topBar.className = 'topBar';
                // goTop.className = 'goTop';
                topBar.classList.remove('active');
                goTop.classList.remove('active');
            }
        }
        goTop.onclick = function() {
            window.scrollTo({
                top: 0,
                behavior: 'smooth'
            })
        }
    </script>
</body>

操作元素样式

  • 样式
    • 行内样式
    • 非行内样式
  • 元素.style
    • console.log(div.style)
    • 只能获取到行内样式
    • div.style.width
  • 获取非行内样式
    • window.getComputedStyle() 方法(标准浏览器)
      • window.getComputedStyle(要获取样式的元素)
      • 返回一个对象,里面包含所有可以设置的样式,每一个样式都有值,如果没有设置则返回默认值
    • currentStyle 属性 (IE低版本)
    • 通过点操作符获取样式的时候,如果样式名带有横线,则用驼峰命名法,如 background-color对应backgroundColor
    • 如果是数组关联语法,则可以写横线, 如style[‘background-color’]
  • 短路表达式:方法或属性执行没有问题,只是拿不到值得时候||
function getStyle(ele, style){
    if ('getComputedStyle' in window){
        return window.getComputedStyle(ele)[style];
    }
    else{
        retuen ele.currentStyle[style];
    }
}
  • 设置元素样式只能设置元素行内样式
    • 元素.style.样式名 = ‘value‘

DOM节点

  • DOM节点就是构成我们页面的每一个组成部分
  • 元素/注释/文本等内容都是一个个节点
  • 常用的四种节点
    • 元素节点:页面中的每一个标签
    • 文本节点:卸载标签里的文本内容
    • 属性节点:写在元素上的每一个属性
    • 注释节点:页面中书写的注释内容
  • document
    • 是一个页面中最大的节点,只能有一个
    • 承载所有节点的容器,不属于元素
    • 根节点
  • html
    • 一个页面中最大的元素节点
    • 承载所有其他节点
    • 根元素节点
  • 元素节点
    • head/body/div/….
    • 只是不同标签在页面中表现形式不一样
    • 特点:只是页面的标签
  • 文本节点
    • 每一段文本内容都是一个文本节点
    • 包含换行和空格
    • 一般作为元素节点的子节点存在,用来表示该元素节点在页面上显示的内容
  • 属性节点
    • 属性节点不作为独立节点出现,必须依赖元素节点
    • 如果没有元素,属性节点就是文本
  • 注释节点
    • 作为独立节点出现
    • 作为说明文本使用
  • 节点操作
    • 不光操作元素,还要操作 注释节点 文本节点 属性节点
    • 获取节点(包括但不限于元素节点)
    • 创建节点(通过JS语法来创造一个标签/文本/注释)
      • 把我们创造的节点插入另一个节点中,出现父子结构
    • 删除节点(把一个已经存在的节点移除)
    • 替换节点(创造一个节点去替换一个已经存在的节点)
    • 克隆节点(把一个已经存在的节点复制一份一模一样的)

获取节点

  • 获得节点的属性
    • childNodes
      • 语法:元素.childNodes
      • 得到元素所有的子节点
    • children
      • 语法:元素.children
      • 得到子节点的所有元素节点
    • firstChild
      • 语法:元素.firstChild
      • 得到元素的第一个子节点
    • firstElementChild
      • 语法:元素.firstElementChild
      • 得到元素第一个子元素节点
    • lastChild
      • 语法:元素.lastChild
      • 得到元素的最后一个子节点
    • lastElementChild
      • 语法:元素.lastElementChild
      • 得到元素最后一个子元素节点
    • perviousSibling
      • 语法:元素.perviousSibling
      • 得到元素的上一个兄弟节点
    • perviousElementSibling
      • 语法:元素.perviousElementSibling
      • 得到元素的上一个兄弟元素
    • nextSibling
      • 语法:元素.nextSibling
      • 得到元素的下一个兄弟节点
    • nextElementSibling
      • 语法:元素.nextSibling
      • 得到元素的下一个兄弟元素
    • parentNode
      • 语法:元素.parentNode
      • 得到该元素的父节点
      • 父节点:大部分时间是元素,有时候是document
    • parentElement
      • 语法:元素.parentElement
      • 得到该元素的父元素节点
    • attributes
      • 语法:元素.attributes
      • 得到元素的所有属性节点
<body>
    <p>div上面</p>
    <div>
        hello
        <p>你好</p>
        world
        <p>世界</p>
        <!--  -->
    </div>
    <p>div下面</p>
    <script>
        // 获取节点
        let div = document.querySelector('div');
        // 1. childNodes
        // let child = div.childNodes;

        // 2. children
        // let childEle = div.children;
        // console.log(childEle);

        // 3. firstChild
        // let first = div.firstChild;
        // console.log(first);

        // 4. firstElementChild
        // let first = div.firstElementChild;
        // console.log(first);

        // 5. lastChild
        // let last = div.lastChild;
        // console.log(last);

        // 6. lastElementChild
        // let lastEle = div.lastElementChild;
        // console.log(lastEle);

        // 7. perviousSibling
        // let pers = div.previousSibling
        // console.log(pers);

        // 8. perviousElementSibling
        // let peres = div.previousElementSibling
        // console.log(peres);

        // 9. nextSibling
        // let nextS = div.nextSibling
        // console.log(nextS);

        // 10. nextElementSibling
        // let nextEleS = div.nextElementSibling
        // console.log(nextEleS);

        // 11. parentNode
        // let parent = div.parentNode;
        // console.log(parent);

        // 12. parentElement
        // let parentEle = div.parentElement;
        // console.log(parentEle);
    </script>
</body>

创建节点

  • createElement()
    • 语法:document.createElement(‘标签名’)
    • 返回值:一个元素节点
  • createTextNode()
    • 语法:document.createTextNode(‘文本内容’)
    • 返回值:一个文本节点,不是字符串
  • createComment()
    • 语法:document.createComment(‘注释内容’)
    • 返回值:一个注释节点
  • createAttribute()
    • 语法:document.createAttribute(‘属性名’)
      • 添加属性值,节点.value = ‘属性值’
    • 返回值:一个属性节点

后面三个用的少

插入节点

  • appendChild()
    • 语法:父节点.appendChild(子节点)
    • 作用:把子节点插入到父节点里面,放在最后一个节点的位置
  • insertBefore()
    • 语法:父节点.insertBefore(要插入的子节点, 哪一个子节点前面)
    • 作用:把子节点插入到指定父节点的指定子节点前面

删除节点

  • 删除一个已经存在的节点 或者 可以在创建的节点里面删除
  • removeChild()
    • 语法:父节点.removeChild(子节点)
    • 作用:把子节点从父节点里面移出
  • remove()
    • 语法:节点.remove()
    • 作用:把自己移出父节点

替换节点

  • 用一个节点替换一个已经存在的节点
  • replaceChild()
    • 语法:父节点.replaceChild(新节点, 旧节点)
    • 作用:在父节点下,用新节点替换旧节点

克隆节点

  • 把某一个节点复制一个一模一样的
  • cloneNode()
    • 语法:节点.cloneNode(参数)
      • 参数选填,默认是 false
    • 返回值:一个克隆好的节点

带有添加和删除功能的表格

<style>
        * {
            margin: 0;
            padding: 0;
        }
        
        form {
            width: 300px;
            padding: 20px;
            margin: 10px;
            border: 10px solid skyblue;
        }
        
        form>button {
            width: 100%;
            height: 30px;
            margin: 10px 0;
        }
        
        table {
            width: 300px;
            margin: 30px;
            border: 2px solid pink;
            text-align: center;
        }
        
        table>tbody>tr:nth-child(odd) {
            background-color: #ccc;
        }
        
        table>tbody>tr:nth-child(even) {
            background-color: orange;
        }
    </style>
</head>

<body>
    <form action="">
        姓名:<input type="text" class="username">
        <br> 年龄:
        <input type="text" class="age">
        <br> 性别:
        <input type="text" class="gender">
        <br> 操作:
        <button type="button" class="add">添加</button>
        <br>
    </form>
    <table cellspacing="0">
        <thead>
            <th>姓名</th>
            <th>年龄</th>
            <th>性别</th>
            <th>操作</th>
        </thead>
        <tbody>
            <tr>
                <td>张三</td>
                <td>18</td>
                <td>男</td>
                <td><button class="del">删除</button></td>
            </tr>
            <tr>
                <td>张四</td>
                <td>20</td>
                <td>女</td>
                <td><button class="del">删除</button></td>
            </tr>
            <tr>
                <td>张五</td>
                <td>22</td>
                <td>男</td>
                <td><button class="del">删除</button></td>
            </tr>
        </tbody>
    </table>

    <script>
        // 分析逻辑
        /*
            1. 点击添加按钮的时候
             => 拿到文本框的内容
             => 组装一个 tr 标签出来
             => 插入到 tbody 里面
            2. 点击每一个删除按钮的时候
             => 找到当前删除按钮所在的 tr 标签,并移除
            
        */

        // 1. 获取元素
        let usernameInp = document.querySelector('.username');
        let ageInp = document.querySelector('.age');
        let genderInp = document.querySelector('.gender');
        let addBtn = document.querySelector('.add');
        let tbody = document.querySelector('tbody');
        let dels = document.querySelectorAll('.del');

        // 2. 添加业务逻辑
        // 2.1 给 添加按钮 绑定点击事件
        addBtn.onclick = function() {
            // 2.2 获取内容
            let username = usernameInp.value;
            let age = ageInp.value;
            let gender = genderInp.value;

            // 2.3 判断非空
            if (username === '' || age === '' || gender === '') {
                alert('请完整填写表单');
                return;
            }

            // 2.4 组装一个合法的节点
            let tr = document.createElement('tr');
            let td1 = document.createElement('td');
            let td2 = document.createElement('td');
            let td3 = document.createElement('td');
            let td4 = document.createElement('td');
            let button = document.createElement('button');

            td1.innerHTML = username;
            td2.innerHTML = age;
            td3.innerHTML = gender;
            button.innerHTML = '删除';

            button.onclick = function() {
                let tr = this.parentElement.parentElement;
                // 把找到的 tr 删除
                tr.remove();
            }

            tr.appendChild(td1);
            tr.appendChild(td2);
            tr.appendChild(td3);
            td4.appendChild(button);
            tr.appendChild(td4);
            tbody.appendChild(tr);

            // 2.5 表单置空
            usernameInp.value = '';
            ageInp.value = '';
            genderInp.value = '';
        }

        // 3. 删除的业务逻辑
        dels.forEach(function(btn) {
            // 3.1 给每个delBtn添加点击事件
            btn.onclick = function() {
                let tr = this.parentElement.parentElement;
                // 把找到的 tr 删除
                tr.remove();
            }
        })
    </script>
</body>

动态创建表格

<body>
    <table>
        <thead>
            <tr>
                <th>姓名</th>
                <th>年龄</th>
                <th>性别</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>张三</td>
                <td>18</td>
                <td>男</td>
            </tr>
            <tr>
                <td>张三</td>
                <td>18</td>
                <td>男</td>
            </tr>
            <tr>
                <td>张三</td>
                <td>18</td>
                <td>男</td>
            </tr>
        </tbody>
    </table>

    <script>
        // 动态创建表格
        let userList = [{
            name: '张三',
            age: 18,
            gender: '男'
        }, {
            name: '张四',
            age: 20,
            gender: '女'
        }, {
            name: '张五',
            age: 22,
            gender: '男'
        }]

        // 0. 获取元素
        let tbody = document.querySelector('tbody');


        let frg = document.createDocumentFragment();
        // let div = document.createElement('div');
        // 1. 遍历数组
        userList.forEach(function(user) {
            // 创建 tr
            let tr = document.createElement('tr');
            // 填充 tr 的内容
            tr.innerHTML =
                `
            <td>${user.name}</td>
            <td>${user.age}</td>
            <td>${user.gender}</td>
            `;
            // div.appendChild(tr);
            frg.appendChild(tr);

        })
        tbody.appendChild(frg);
    </script>
</body>
  • 操作 DOM 越多,性能越差
  • 文档碎片(筐)
    • 我们可以用JS创建一个文档碎片节点
    • 可以承载节点
    • 当你把筐向页面添加的时候
      • 筐是不会进入页面的,而是把筐里面的内容倒进去
    • 语法:document.createDocumentFragment()
    • 返回值:一个文档碎片节点

获取元素尺寸

  • 元素的占地面积
  • 占地面积:内容区域 + padding + border
  • 两组方式
    • offsetWidth 和 offsetHeight
      • 语法
        • 元素.offsetWidth
        • 元素.offsetHeight
      • 得到元素 内容 + padding +border 的尺寸
      • 注意:display:none 的时候得到的时候是0
      • 因为这个时候不占位
    • clinetWidth 和 clinetHeight
      • 语法
        • 元素.clientWidth
        • 元素.clientHeight
      • 得到元素 内容 + padding 区域的尺寸
      • 注意:display:none 以后是 0

获取元素偏移量

  • 获取元素偏移量
    • 一个元素相对于参考系的坐标位置
  • offsetParent
    • 语法:元素.offsetParent
    • 拿到该元素获取偏移量的时候的参考父级
      • 当你想给这个元素设置一个绝对定位的时候会根据谁定位,他的offsetParent 就是谁
  • offsetLeft 和 offsetTop
    • 语法:元素.offsetLeft 和 元素.offsetTop
    • 得到对于参考父级的左边和上边的偏移量

获取浏览器窗口尺寸

  • 获取浏览器窗口尺寸
    • BOM 级别的获取
      • innerWidth
      • innerHeight
      • 拿到的是包含滚动条的尺寸
    • DOM 级别的的获取
      • 其实就是获取页面的那一部分尺寸
      • document.documentElement.clientWidth
      • document.documentElement.clientHeight
// 获取浏览器尺寸
// 包括滚动条
console.log('BOM: ');
console.log('width: ', window.innerWidth);
console.log('height: ', window.innerHeight);

console.log('DOM: ');
console.log('width: ', document.documentElement.clientWidth);
console.log('height: ', document.documentElement.clientHeight);

元素的常用事件

  • 事件分类
    • 鼠标事件
    • 键盘事件
    • 浏览器事件
    • 表单时间
    • 拖拽事件
    • 触摸事件(移动端)
    • 其他事件
  • JS里面的所有原生事件没有大写字母
  • 鼠标事件
    • click(鼠标左键单击)
    • dblclick(鼠标左键双击)
    • contextmenu(鼠标右键单击)
    • mousewheel(滚轮滚动事件)
    • 上面是四个基本事件
    • mousedown(鼠标按下)
      • 不光是左键,右键也可以,滚轮键也可以,侧键也可以(有时候不可)
    • mouseup(鼠标抬起)
      • 不光是左键,右键也可以,滚轮键也可以,侧键也可以(有时候不可)
    • mousemove(鼠标移动)
    • mouseover
    • mouseout
    • mouseover
    • mouseout
    • mouseenter
    • mouseleave
  • 键盘事件
    • 不是所有元素都能触发
    • 表单元素(有选中效果),document,window
    • keydown(键盘按下, 中文输入法下也有效果)
    • keyup(键盘抬起)
    • keypress(键盘按下, 必须要能够准确嵌入到文本框里的,键入的内容要与你按下的内容一致)
  • 浏览器事件
    • load(页面加载完毕)
    • scroll(滚动)
    • resize(窗口尺寸改变)
    • offline(网络断开)
    • online(网络恢复)
    • hashchange(hash值改变的时候)
  • 表单事件
    • 表单时间绑定给 表单元素 和 form标签 的
    • change(表单内容改变,当表单失去焦点的时候和聚焦的时候不一样)
    • input(输入内容)
    • focus(表单聚焦)
    • blur(表单失焦)
    • submit(表单提交事件)
      • 绑定给 form 标签使用的
    • reset(表单重置事件)
      • 时间是绑定给 form 标签使用的
      • 当你点击 reset 按钮才能触发
  • 拖拽事件
    • 一般元素想触发拖拽行为,要给元素加一个属性(img自带)
    • draggable = “true”
    • 需要两个元素才能完成一个完整的拖拽
      • 拖拽元素
      • 目标元素
    • dragstart(拖拽开始)
      • 绑定给拖拽元素的
    • drag(拖拽移动)
      • 绑定给拖拽元素的
    • dragend(拖拽结束)
      • 绑定给拖拽的元素的
    • dragenter(拖拽进入目标元素)(光标)
      • 绑定给目标元素
    • dragleave(拖拽离开目标元素)
      • 绑定给目标元素
    • dragover(脱妆元素在目标元素里面移动)
      • 绑定给目标元素
    • drop(拖拽元素在目标元素内放手)
      • 绑定给目标元素
      • 必须要在 dragover 里面阻止默认行为
  • 触摸事件
    • 只能在移动端使用
    • touchstart(触摸开始)
    • touchmove(触摸结束)
    • touchend(触摸开始)
  • 其他事件
    • transitionend(过度结束)
      • 当你有过渡属性的时候
      • 过渡结束触发
      • 过渡结束触发,你过渡几个属性触发多少次
    • selectstart(开始选择)
      • 当你想在页面中框选文档的时候触发
    • visibilitychange(窗口显示和隐藏)
      • 只能绑定给document
    • ……
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        .div {
            width: 200px;
            height: 200px;
            background-color: skyblue;
            transition: all 3s linear;
        }
        
        .dragp {
            width: 200px;
            height: 200px;
            background-color: red;
        }
        /* .div:hover {
            width: 500px;
            height: 500px;
        } */
    </style>

</head>

<body>
    <!-- <div class="div"></div>
    <form action="">
        <input type="text" name="aaa">
        <button>提交</button>
        <input type="reset">
    </form> -->
    <div draggable="true" class="dragdiv div">
    </div>
    qwertyuiop
    <p class="dragp"></p>
    <script>
        // 获取元素
        let div = document.querySelector('.div');

        // 1. 鼠标事件
        // 1.1 click
        // div.onclick = function() {
        //     console.log('左键单击');
        // }

        // 1.2 dblclick
        // div.ondblclick = function() {
        //     console.log('左键双击');
        // }

        // 1.3 contextmenu
        // div.oncontextmenu = function() {
        //     console.log('右键单击');
        // }

        // 1.4 mousewheel(没有鼠标,测试不了)
        // div.onmousewheel = function() {
        //     console.log('滚轮事件');
        // }

        // 1.5 mousedown
        // div.onmousedown = function() {
        //     console.log('鼠标按下');
        // }

        // 1.6 mouseup
        // div.onmouseup = function() {
        //     console.log('鼠标抬起');
        // }

        // 1.7 mousemove
        // div.onmousemove = function() {
        //     console.log('鼠标移动');
        // }

        // 1.8 mouseover
        // div.onmouseover = function() {
        //     console.log('鼠标移入');
        // }

        // 1.9 mouseout
        // div.onmouseout = function() {
        //     console.log('鼠标移出');
        // }

        // 1.10 mouseenter
        // div.onmouseenter =function (){
        //     console.log('鼠标移入');
        // }

        // 1.11 mouseleave
        // div.onmouseleave = function (){
        //     console.log('鼠标移出');
        // }


        // 获取元素
        let inp = document.querySelector('input');

        // 键盘事件
        // 2.1 keydown
        // inp.onkeydown = function() {
        //     console.log('键盘按下');
        // }

        // 2.2 keyup
        // inp.onkeyup = function() {
        //     console.log('键盘抬起');
        // }

        // 2.3 keypress
        // inp.onkeypress = function() {
        //     console.log('键盘按下');
        // }

        // 3. 浏览器事件
        // 3.4 offline
        // window.onoffline = function() {
        //     console.log('断网了');
        // }

        // 3.5 online
        // window.ononlone = function() {
        //     console.log('网络恢复了');
        // }

        // 3.6 hashchange
        // window.onhashchange = function() {
        //     console.log('hash值改变了');
        // }


        // let inp = document.querySelector('input');
        let form = document.querySelector('form');
        // 4. 表单时间
        // 4.1 change
        // inp.onchange = function() {
        //     console.log('表单发生改变');
        // }

        // 4.2 input
        // inp.oninput = function() {
        //     console.log('输入事件');
        // }

        // 4.3 focus
        // inp.onfocus = function() {
        //     console.log('聚焦');
        // }

        // 4.4 blur
        // inp.onblur = function() {
        //     console.log('失焦');
        // }

        // 4.5 submit
        // form.onsubmit = function() {
        //     console.log('表单提交');
        //     // 阻止提交
        //     return false;
        // }

        // 4.6 reset
        // form.onreset = function() {
        //     console.log('表单重置');
        // }

        // 5. 拖拽事件
        let dragdiv = document.querySelector('.dragdiv');
        let p = document.querySelector('.dragp');

        // 5.1 dragstart
        // dragdiv.ondragstart = function() {
        //     console.log('开始拖拽');
        // }

        // 5.2 drag
        // dragdiv.ondrag = function() {
        //     console.log('正在拖拽');
        // }

        // 5.3 dragend
        // dragdiv.ondragend = function() {
        //     console.log('拖拽结束');
        // }

        // 5.4 dragenter(光标)
        // p.ondragenter = function() {
        //     console.log('光标进入');
        // }

        // 5.5 dragleave
        // p.ondragleave = function() {
        //     console.log('光标离开');
        // }

        // 5.6 dragover
        // p.ondragover = function(e) {
        //         // 阻止默认行为
        //         e.preventDefault();
        //         console.log('在目标元素中移动');
        // }

        // 5.7 drop
        // p.ondrop = function() {
        //     console.log('在目标元素内放手');
        // }

        // 6. 触摸事件
        // 6.1 touchstart
        // div.ontouchstart = function() {
        //     console.log('触摸开始');
        // }

        // 6.2 touchmove
        // div.ontouchmove = function() {
        //     console.log('触摸移动');
        // }

        // 6.3 touchend
        // div.ontouchend = function() {
        //     console.log('触摸结束');
        // }

        // 7.  其他事件
        // 7.1 transitionend
        // div.ontransitionend = function() {
        //     console.log('过渡结束');
        // }

        // 7.2 selectstart
        // document.onselectstart = function(e) {
        //     // 清除默认事件
        //     e.preventDefault();
        //     console.log('请支付后复制');
        // }

        // 7.3 visibilitychange
        // document.onvisibilitychange = function() {
        //     console.log('显示状态改变了');
        // }
    </script>
</body>
</html>

二级菜单渲染

选择器