一、DOM节点的增删改查

DOM:document object model 文档对象模型

1. 创建新节点

  1. createDocumentFrafment() //创建一个DOM片段
  2. createElement() //创建一个具体元素
  3. createTextNode() //创建一个文本节点

2. 增删、替换、插入

  1. appendChild() //后增
  2. inserBefore(newChild,oldChild) //前增,插入
  3. removeChild() //移除
  4. replaceChild(newChild,oldChild) //替换

3. 查询节点

  1. document.getElementById("id") //通过Id查找节点
  2. document.getElementByClassName("class") //通过类名获取
  3. document.getElementsByName("name") //通过name获取
  4. document.getElementsByTagName() //通过标签名获取
  5. //<p name="text"> hello world</p>
  6. //如果要指向包含hello world这个文本节点的 p元素节点 那么下面的指向应该加上[0]
  7. //var p = document.getElementsByTagName('p')[0];
  8. document.querySelectorAll() //通过选择器查询
  9. //<p name="text" class="one"> hello world</p>
  10. //var one = document.querySelectorAll('.one');

二、Classlist方法

2-1 Javascript中

判断元素是否有某个class

obj.classList.contains()

  1. <div id="test">hello world</div>
  2. var test = document.getElementById("test");
  3. test.onclick = function(){
  4. if(this.classList.contains("current")){
  5. this.className = ""
  6. }else{
  7. this.className = "current"
  8. }
  9. }

操作元素class

  1. add() 添加Class
  2. remove() 移除Class
  3. contains() 切换
<p id="p">hello world</p>
     <button id="btn">addClass</button>
     <button id="removeClass">removeClass</button>
     <button id="toggle">toggleClass</button>
     <!-- classList
        add()  添加Class
        remove()  移除Class
        contains()  切换
     -->
     <script>
         var btn = document.getElementById("btn")
         var p = document.getElementById("p")
         var remove = document.getElementById("removeClass")
         var toggle = document.getElementById("toggle")
         btn.onclick = function(){
             p.classList.add("active")
         }
         remove.onclick = function(){
             p.classList.remove("active")
         }
         toggle.onclick = function(){
             p.classList.toggle("active")
         }
     </script>
prepend()在父元素的第一位增加元素
append()在父元素的最后一位增加元素
        <div id="parent">
             <p>hello world</p>
        </div>
    <script>
        var parent = document.getElementById("parent")
        var h1 = document.createElement("h1")
        h1.innerHTML= '前面'
        parent.prepend(h1)
        parent.append("后面")
    </script>

image.png

<p id="p">hello world</p>
    <script>
        /* 
        发生在兄弟元素之间
        before  前面
        after   后面
         */
        var p = document.getElementById("p")
        p.before("前面")
        p.after("后面")
    </script>

image.png

2-2 jQuery中操作class

hasClass (判断是否存在一个class) addClass removeClass toggleClass remove() 移除元素

<style>
      .current{
          background: red;
      }
    </style>
</head>
<body>
    <p>hello world</p>
    <button id="add">addClass</button>
    <button id="remove">removeClass</button>
    <button id="toggle">toggleClass</button>
    <button id="delete">delete</button>
    <script>
         $("#add").click(function(){
             $("p").addClass("current")
         })
         $("#remove").click(function(){
             $("p").removeClass("current")
         })
         $("#toggle").click(function(){
             /* $("p").toggleClass("current") */
             if($("p").hasClass("current")){
                $("p").removeClass("current")
             }else{
                $("p").addClass("current")
             }
         })
         $("#delete").click(function(){
             $("p").remove()
         })
    </script>

三、节点分类

1.元素节点 nodeType==1

2.属性节点 nodeType==2 aNode

3.文本节点 nodeType==3 tNode

firstChild 输出第一个节点 firstElementChild 输出第一个元素节点

 <div id="parent">ffid<p>hello world</p>
    </div>
<script>
    var parent=document.getElementById("parent")
    var tNode=parent.firstChild;
    var aNode=parent.getAttributeNode("id")
    console.log(parent.firstChild)   //"ffid"
    console.log(parent.firstElementChild)   //<p>hello world</p>
    console.log(parent.nodeType)   //1  元素节点  <div id="parent">ffid<p>hello world</p>
    console.log(aNode.nodeType)    //2  属性节点  id="parent"
    console.log(tNode.nodeType)    //3  文本节点  "ffid"
</script>

四、克隆节点

        <p class="test">hello</p>
    <script>
       var test=document.getElementsByClassName("test")[0];
       var cTest=test.cloneNode(true);
       document.body.appendChild(cTest)
    </script>

五、自定义属性

    <div id="test" class="one" data-uid="two">hello world</div>
    <script>
    var test=document.getElementById("test")
    console.log(test.id)   //test
    console.log(test.className)   //one
    console.log(test.dataset.uid)   //two
    </script>

六、childNodes属性

定义:让我们可以从给定文档的节点树里把任何一个元素的子元素检索出来,返回一个数组,这个数组包含给定元素的全体子元素

 <script>
       function countBodyChildren(){
           var body_element=document.getElementsByTagName("body")[0]
           alert(body_element.childNodes.length)
       }
       window.onload=countBodyChildren
    </script>

七、事件冒泡、事件捕获、事件监听

事件冒泡

子元素和父元素绑定了相同的事件,子元素的执行,父元素的事件也会触发
阻止事件冒泡: event.stopPropagation();

        <div id="parent">
        <div id="child">
            哈哈
        </div>
    </div>

      <script>
       var parent=document.getElementById("parent")
       var child=document.getElementById("child")
       parent.onclick=function(event){
           alert("parent")
           event.stopPropagation()
       }
       child.onclick=function(event){
           alert("child")
           event.stopPropagation()
       }
      </script>

      //child
      //parent

事件捕获

从不太具体的节点 最早接收事件,而最具体的节点,最后接收事件 从外向内
addEventListener(“事件名” , “事件处理函数” , “布尔值”);
false —>事件冒泡
true —>事件捕获

<div id="parent">
        <div id="child">
            哈哈
        </div>
    </div>

    <script>
        var parent = document.getElementById("parent")
        var child = document.getElementById("child")
        child.addEventListener('click', function (event) {
            alert("child")
        }, true)
        parent.addEventListener('click', function (event) {
            alert("parent")
        }, true)
    </script>
//parent
//child

事件监听

    onclick   --直接绑定的方式,只会触发一次
   addEventListener(event,function,boolean)
   removeEventListener(event,function,boolean)

八、错误处理

try…catch

try    {
            有可能出现错误的代码写在这里
        }
catch    {
                出错后的处理
            }
//如果try中的代码没有出错,则程序正常运行try中的内容后,不会执行catch中的内容,
//如果try中的代码一但出错,程序立即跳入catch中去执行代码,那么try中出错代码后的所有代码就不再执行了

九、操作元素的属性

1.setAttribute jquery attr(attrName,value) 设置属性 为class设置

2.getAttribute jquery attr(attrName) 获取属性

3.removeAttribute jquery removeAttr(attrName) 移除属性

1.js
   <p id="p" class="one">hello world</p>
    <script>
       var p=document.getElementById("P");
       p.onclick=function(){
           this.setAttribute("style","display:none")
       }
       console.log(p.getAttribute("class"))
       console.log(p.removeAttribute("class"))
    </script>
2.jquery
    <p id="p" class="one">hello world</p>
    <script>
        $("p").click(function(){
            $("this").attr("id","good")
            console.log($(this).attr("id"))
            $(this).removeAttr("class")
        })
    </script>

4.cssText 批量操作属性

5.length 获取长度

6.getPropertyValue() 获取style属性里面的值

7.item 方法接收一个整数作为参数值,返回该位置的css属性名

8.removeProperty() 移除style里面的值

9.setProperty() 改变style里面的值

<p id="test">hello world</p>
<script>
var test=document.getElementById("test")
       test.style.cssText="color:pink;background:#333;font-size:14px;border:1px solid red";
       console.log(test.style.getPropertyValue("color"))
       console.log(test.style.item(0))
       test.onclick=function(){
           this.style.removeProperty("color")
           this.style.setProperty("background-color","green")
       }
</script>

十、文档碎片

文档碎片可以提高DOM操作属性 脱离于文档 原理:将DOM暂寄存到fragment上,之后一次添加BOM上就可以了

 <ul id="parent"></ul>
    <script>
        var parent=document.getElementById("parent")
        var frag=document.createDocumentFragment();
        for(var i=0;i<=10;i++){
            /* 寄存到文档碎片上 */
            var li=document.createElement("li");
            li.innerHTML="i";
           /*  parent.appendChild(li); */
            frag.appendChild(li)
        }
        parent.appendChild(frag)
    </script>

十一、JS事件

1.onfoucs —>获取焦点

2.onblur —>失去焦点

<input type="text" id="input">
    <script>
        /* onfocus  -->获取焦点
        onblur  -->失去焦点
         */
         var input = document.getElementById("input");
         input.onfocus = function(){
             this.style.backgroundColor = "red"
         }
         input.onblur = function(){
             this.style.backgroundColor = "green"
         }
         /* 键盘松开的时候发生的事件 */
         input.onkeyup = function(event){
            /* console.log(event.keyCode) */  //keyCode 返回一个键盘码
            if(event.keyCode == 13){
                /* 只要是对象的属性,都可以通过点的方式去获取值 */
                console.log(this.value)
            }
         }
    </script>

3.onclick —>点击事件

4.onmouseover —>鼠标触碰事件

5.onmouseout —>鼠标移去事件

<script>
        var test =document.getElementById("test");
        /* 事件
            onclick 点击事件
            onmouseover 鼠标触碰事件
            onmouseout  鼠标移去

        */
        test.onclick=function(){
            // this.在事件中指向正在执行事件的当前对象
            this.style.color="red"
            // innerHTML
            this.innerHTML="change"
        }
        test.onmouseover=function(){
            this.style.backgroundColor="#121212";
        }
        test.onmouseout=function(){
            this.style.backgroundColor="#fff";
        }

6.onkeyup —>键盘松开事件

input.onkeyup = function(event){
            /* console.log(event.keyCode) */  //keyCode 返回一个键盘码
            if(event.keyCode == 13){
                /* 只要是对象的属性,都可以通过点的方式去获取值 */
                console.log(this.value)
            }

7.onscroll —>窗口滚动事件

        body{
            height: 2000px;
        }
        .nav{
            line-height: 60px;
            text-align: center;
            height: 60px;
            position: fixed;
            background: transparent;
            left: 0;
            top: 0;
            width: 100%;
        }

<div class="nav" id="nav">导航</div>
    <script>
        /* onscroll  滚动事件 */
        var nav = document.getElementById("nav")
        window.onscroll = function(){
            /* 获取滚动条距离顶部的高度 */
            var scrollTop = document.documentElement.scrollTop;
            /* 当滚动条距离顶部高度达到300时候完全显示 */
            var opacity = scrollTop/300;
            if(opacity>1){
                opacity = 1
            }
            nav.style.opacity = opacity;
            nav.style.backgroundColor = "red"
        }
    </script>

8.onload —>页面加载事件

<input type="text" id="input">
    <script>
        /* 
        onload 等DOM树以及图片相关资源加载完毕,再执行函数中的代码
        */
        window.onload = function(){
            var input = document.getElementById("input");
            input.onchange = function(event){
                console.log(this.value)
            }
        }
    </script>

9.onchange —>域的内容改变时发生

<textarea name="" id="txt" cols="30" rows="10"></textarea>
    <script>
        var txt = document.getElementById("txt");
        txt.onchange = function(){
            console.log(1)
        }
    </script>

10.onsubmit —>表单中的确认按钮被点击时发生

<form name="form" id="form">
        <p><input type="text" name="username"></p>
        <p><input type="text" name="email"></p>
        <p><input type="submit"></p>
    </form>
    <script>
        var form = document.getElementById("form");
        form.onsubmit = function(){
            console.log(this.username.value)
            console.log(this.email.value)
            return false;
        }
    </script>

11.onresize —>浏览器的尺寸发生改变

<script>
        window.onresize = function(){
            /* window.innerWidth    获取窗口的width */
            console.log(window.innerWidth)
        }
    </script>

12.onmousedown —>鼠标按下

13.onmouseup —>鼠标松开

14.onmousemove —>鼠标指针移动时发生。

十二、事件循环

遇到同步任务直接执行,遇到异步任务分类为macro-task(宏任务)与micro-task(微任务),在最新标准中,它们被分别称为task与jobs。

  1. 宏队列 macro-task script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
  2. 微队列 micro-task process.nextTick, Promise, Object.observe(已废弃), MutationObserver(html5新特性)。process.nextTick会先于Promise.then执行

Tip:有微则微,无微则宏
一、DOM - 图3

示例代码:

代码1:

<script>
    const first = () => (new Promise((resolve, reject) => {
        console.log(3);
        let p = new Promise((resolve, reject) => {
            console.log(7);
            setTimeout(() => {
                console.log(5);
                resolve(6);
            }, 0)
            resolve(1);
        });
        resolve(2);
        p.then((arg) => {
            console.log(arg);
        });
    }));
    first().then((arg) => {
        console.log(arg);
    });
    console.log(4);
</script>
//输出: 3、7、4、1、2、5

代码2:

// 这是一个同步任务
console.log('1')            --------> 直接被执行
                                      目前打印结果为:1
// 这是一个宏任务
setTimeout(function () {    --------> 整体的setTimeout被放进宏任务列表
  console.log('2')                    目前宏任务列表记为【s2】
});

new Promise(function (resolve) {
  // 这里是同步任务
  console.log('3');         --------> 直接被执行
  resolve();                          目前打印结果为:1、3
  // then是一个微任务
}).then(function () {       --------> 整体的then[包含里面的setTimeout]被放进微任务列表
  console.log('4')                    目前微任务列表记为【t45】
  setTimeout(function () {
    console.log('5')
  });
});

接上↑

第一轮小结:
执行到这里的结果:1、3

宏任务列表如下:
setTimeout(function () {
  console.log('2')
});

微任务列表如下:
then(function () {
  console.log('4')
  setTimeout(function () {
    console.log('5')
  });
});

接上↑

浏览器瞅了一眼微任务列表 发现里面有微任务 就开始全部执行
then(function () {
  console.log('4')            --------> 直接被执行
                                        目前打印结果为:1、3、4
  setTimeout(function () {    --------> 被放进宏任务列表了
    console.log('5')                    目前宏任务列表记为【s2、s5】
  });
});


浏览器发现微任务执行完毕了

开始执行宏任务列表

setTimeout(function () {
  console.log('2')   --------> 直接被执行
                               目前打印结果为:1、3、4、2

});

setTimeout(function () {
  console.log('5')   --------> 直接被执行
                               目前打印顺序为: 1、3、4、2、5、5
});

最终结果为: 1、3、4、2、5