JavaScript基础知识(Dom)

1/30/2021 JavaScript

# DOM

/*
1.什么是window?
    window:是一个全局对象, 代表浏览器中一个打开的窗口, 每个窗口都是一个window对象

2.什么是document?
    document是window的一个属性, 这个属性是一个对象
document: 代表当前窗口中的整个网页,
    document对象保存了网页上所有的内容, 通过document对象就可以操作网页上的内容

3.什么是DOM?
DOM 定义了访问和操作 HTML文档(网页)的标准方法
DOM全称: Document Object Model, 即文档模型对象
所以学习DOM就是学习如何通过document对象操作网页上的内容
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 获取DOM元素

    //通过id获取
    let oDiv = document.getElementById("box");

    //通过class获取
    let oDivs = document.getElementsByClassName('father');

    //通过标签名获取
    let inpS = document.getElementsByTagName('div');

    // 通过name名称获取
    let names = document.getElementsByName('test');
    
    //通过选择器获取
    // querySelector只会返回根据选择器找到的第一个元素
    let oDiv = document.querySelector('#box');
    // document.querySelector('div>form');
    
    // querySelectorAll返回根据选择器找到的多个元素
    let oDivs = document.querySelectorAll('.father');
    
    ---------------------------------------------
    
    // children 获取指定元素所有的子元素
    console.log(oDiv.children);
    // childNodes 获取指定元素所有的节点
    console.log(oDiv.childNodes);
    //获取指定节点中的第一个子节点
    oDiv.firstChild
    //获取指定节点中的第一个子元素
    oDiv.firstElementChild
    //获取指定节点中的最后一个子节点
    oDiv.lastChild
    //获取指定节点中的最后一个子元素
    oDiv.lastElementChild
    // 通过子元素获取父元素/父节点
    let item = document.querySelector('.item');
    item.parentElement;//父元素
    item.parentNode;//父节点
    let parentEle = item.parentElement || item.parentNode //兼容写法
    //获取相邻上一个节点
    item.previousSibling
    //获取相邻上一个元素
    item.previousElementSibling
    //获取相邻下一个节点
    item.nextSibling
    //获取相邻下一个元素
    item.nextElementSibling
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# 节点增删改查

//1.创建节点
let oSpan = document.createElement("span");

//2.添加节点 appendChild()会将指定的元素添加到最后
let oDiv = document.querySelector("div");
//将span标签添加到div中
oDiv.appendChild(oSpan);

// 3.插入节点 insertBefore()
let oH1 = document.querySelector("h1");
oDiv.insertBefore(oSpan,oH1);

//4.删除节点  通过父元素删除指定的子元素
// (在js中如果想要删除某一个元素,只能通过对应的父元素来删除)
oSpan.parentNode.removeChild(oSpan);

//克隆节点 cloneNode()默认不会克隆子元素,如果想克隆子元素需要传递一个true
let newDiv = oDiv.cloneNode(true);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 元素属性操作

//1.获取元素属性
let oImg = document.querySelector("img");
//console.dir()可以显示一个对象所有的属性和方法。

//  通过对象.属性的方式无法获取到自定义属性的取值,
//  通过getAttribute()可以获取到自定义属性的取值
// console.log(oImg.alt);
let ojj = oImg.getAttribute("alt");

//修改元素属性
// setAttribute()可以修改自定义属性的取值
// oImg.title = "新的title"
oImg.setAttribute("title","新的title666");

//新增元素的属性
// setAttribute() 如果属性不存在就是新增,如果属性存在就修改
oImg.setAttribute("it999","feifan");

// 删除元素属性
// oImg.alt = ""; //只能清空自带的属性
oImg.removeAttribute("alt");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 元素内容操作

// 1.获取元素内容
/*
    1.innerHTML获取的内容包含标签,innerText/textContent获取的内容不包含标签
    2.innerHTML/textContent 获取的内容不会去除两端的空格,innerText获取的内容会去除两端的空格
*/
let Odiv = document.querySelector("div")
console.log(Odiv.innerHTML);
console.log(Odiv.innerText);
console.log(Odiv.textContent);

// 2.设置元素内容
/*
    无论通过innerHTML/innerText/textContent设置内容,新的内容都会覆盖原有内容
    通过innerHTML设置数据,数据中包含标签,会转换成标签之后再添加
    通过innerText/textContent设置数据,数据中包含标签,不会转化成标签,会当成一个字符串直接设置
*/
// Odiv.innerHTML = "text";
Odiv.innerHTML = "<span>还行</span>"

//兼容结合写法
function setText(obj,text){
   if ("textContent" in obj){
       obj.textContent = text;
   }else {
       obj.innerHTML = text;
   }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 操作元素样式

//1.设置元素样式
let oDiv = document.querySelector('div');
// oDiv.className = 'box';
//方式二:过去CSS中通过-连接的样式,在JS中都是驼峰命名
//通过js添加的样式都是行类样式,会覆盖同名的css样式
oDiv.style.width = "300px";
oDiv.style.height = "300px";
oDiv.style.backgroundColor = "pink";

//2.获取元素的样式
//通过style属性只能过去到行内样式的属性值,获取不到CSS设置的属性值
// console.log(oDiv.style.width);
let style = window.getComputedStyle(oDiv);
// 如果想获取到css设置的属性值,必须通过window.getComputedStyle()方法来获取
//参数是要获取的元素对象,返回的对象保存了css设置的样式和属性值
console.log(style.width)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# DOM事件

let oBtn = document.querySelector('button');
/*
元素.事件名称 = function(){ }
 */
oBtn.ondblclick = function (){
    alert("双击了")
}
//如果给元素添加了和系统同名的事件,我们添加的事件不会覆盖系统添加的事件
let oA = document.querySelector('a');
oA.onclick = function (){
    alert("还行");
    //用我们添加的事件覆盖掉系统同名的事件 return false
    return false;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

图片

# 定时器

// 1.重复执行的定时器
// window.setInterval(function (){
//     console.log("a");
// },1000);
let startBtn = document.querySelector("#start");
let id = null;
startBtn.onclick = function () {
    id = setInterval(function () {
        console.log("6666");
    }, 1000);
}
let closeBtn = document.querySelector("#close");
closeBtn.onclick = function () {
    clearInterval(id);
}

//2.只执行一次的定时器
// window.setTimeout(function (){
//     console.log("1000执行");
// },1000);
let startBtn = document.querySelector("#start");
let closeBtn = document.querySelector("#close");
let id = null;
startBtn.onclick = function () {
    id = window.setTimeout(function () {
        console.log("9999");
    }, 5000);
}
closeBtn.onclick = function () {
    clearTimeout(id);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 箭头函数

<!--
* 作用: 定义匿名函数
* 基本语法:
  * 没有参数: () => console.log('xxxx')
  * 一个参数: i => i+2
  * 大于一个参数: (i,j) => i+j
  * 函数体不用大括号: 默认返回结果
  * 函数体如果有多个语句, 需要用{}包围,若有需要返回的内容,需要手动返回
* 使用场景: 多用来定义回调函数

* 箭头函数的特点:
    1、简洁
    2、箭头函数没有自己的this,箭头函数的this不是调用的时候决定的,而是在定义的时候处在的对象就是它的this
   3、扩展理解: 箭头函数的this看外层的是否有函数,
        如果有,外层函数的this就是内部箭头函数的this,
        如果没有,则this是window。
-->
let fun = (x, y) => {
    console.log(x, y);
    return x + y;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 简易图片展示

<div>
    <img src="images/ad1.jpg" alt="">
    <ul>
        <li><img src="images/ad1.jpg" alt=""></li>
        <li><img src="images/ad2.jpg" alt=""></li>
    </ul>
</div>
<script type="text/javascript">
    let oImg = document.querySelector("div>img");
    let oItems = document.querySelectorAll("li>img");
    for (let o of oItems) {
        // o.onclick = function (){
        //     //将li>img中的scr地址复制给div>img
        //     oImg.src = this.src;
        // }
        o.onclick = change;

        function change() {
            oImg.src = this.src;
        }
    }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 简易轮播图

<body>
<div>
    <img src="images/ad1.jpg" alt="">
    <p>
        <span id="pre">&lt;</span>
        <span id="next">&gt;</span>
    </p>
</div>
<script type="text/javascript">
    //获取需要操作的元素
    let oImg = document.querySelector("img");
    let preBtn = document.querySelector("#pre");
    let nextBtn = document.querySelector("#next");
    //定义数组保存展示的图片
    let images = [
        "images/ad1.jpg",
        "images/ad2.jpg",
        "images/ad3.jpg",
        "images/ad4.jpg",
        "images/ad5.jpg",
    ];
    let currentIndex = 0;
    let maxIndex = images.length - 1;
    //监听按钮点击事件
    preBtn.onclick = function () {
        currentIndex--;
        if (currentIndex < 0) {
            currentIndex = maxIndex;
        }
        oImg.src = images[currentIndex];
    }

    nextBtn.onclick = function () {
        currentIndex++;
        if (currentIndex > maxIndex) {
            currentIndex = 0;
        }
        oImg.src = images[currentIndex];
    }
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

# 移入移出事件

<script type="text/javascript">
    let oDiv = document.querySelector("div");
    //1.移入事件
    oDiv.onmouseover = function () {
        alert("移入");
    }
    //对于新手来说,为了避免未知的一些BUG,建议使用onmouseenter
    oDiv.onmouseenter = function () {
        alert("移入");
    }

    //2.移出事件
    oDiv.onmouseout = function () {
        alert("移出");
    }
    //新手建议使用onmouseleave
    oDiv.onmouseleave = function () {
        alert("出");
    }

    //移动事件
    oDiv.onmousemove = function () {
        console.log("移动事件");
    }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 表单 焦点事件

let OInput = document.querySelector("input");
// 1.监听input获取焦点
OInput.onfocus = function () {
    console.log("获取到了焦点");
}
// 2.监听input失去焦点
OInput.onblur = function () {
    console.log("失去焦点");
}
// 3.监听input内容改变
// 注意点:onchange事件只有表单失去焦点的时候,才能拿到修改之后的数据
/*    OInput.onchange = function () {
        console.log(this.value);
    }*/
//onihput事件可以时时获取到用户修改之后的数据,只要用户修改了数据就会调用(执行) IE9+
// 在IE9以下,如果想时时的获取到用户修改之后的数据,可以通过onpropertychange事件来实现
OInput.oninput = function () {
    console.log(this.value);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 闭包

/*
1.什么是闭包(closure)?   闭包是一种特殊的函数。

2.如何生成一个闭包?
    当一个内部函数引用了外部函数的数据(变量/函数)时, 那么内部的函数就是闭包
    所以只要满足"是函数嵌套"、"内部函数引用外部函数数据"

3.闭包特点:
    只要闭包还在使用外部函数的数据, 那么外部的数据就一直不会被释放
    也就是说可以延长外部函数数据的生命周期

4.闭包注意点:
    当后续不需要使用闭包时候, 一定要手动将闭包设置为null, 否则会出现内存泄漏
*/
function test() {
    var i = 666;
    //
    return function demo() {
        console.log(i);
    }
}
let fn = test();
fn();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 添加事件的三种方式

var oBtn = document.getElementById("btn");
/*
1.通过onxxx的方式来添加
注意点:由于是给属性赋值,所以后赋值的会覆盖先赋值
 */
oBtn.onclick = function () {
    alert("ddd");
}

/*
2.通过addEventListener方法添加注意点:
1.事件名称不需要添加on
2.后添加的不会覆盖先添加的
3.只支持最新的浏览器IE9
 */

    oBtn.addEventListener("click", function () {
        alert("666");
    });

// 只支持低级浏览器
/*
oBtn.attachEvent("onclick", function () {
    alert("aaa");
});*/
addEvent(oBtn, "click", function () {
    alert("999");
})

function addEvent(ele, name, fn) {
    if (ele.attachEvents) {
        ele.attachEvents("on" + name, fn);
    } else {
        ele.addEventListener(name, fn);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 排他思想

//  清除其它非选中元素的样式,只设置当前选中元素样式
let oItems = document.querySelectorAll("li");
let previousIndex = 0;

for (var i = 0; i < oItems.length; i++) {
    var item = oItems[i];
    (function (index) {
        item.onclick = function () {
            let preItem = oItems[previousIndex];
            preItem.className = "";
            this.className = "current";
            previousIndex = index;
        }
    })(i)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 事件捕获和冒泡

图片

/*
    1.事件的三个阶段
    1.1.捕获阶段(从外向内的传递事件)
    1.2.当前目标阶段
    1.3.冒泡的阶段(从内向外的传递事件)

    2.注意点:
    三个阶段只有两个会被同时执行
    要么捕获和当前, 要么当前和冒泡
*/
/*
1.如何设置事件到底是捕获还是冒泡?
通过addEventListener方法, 这个方法接收三个参数
第一个参数: 事件的名称
第二个参数: 回调函数
第三个参数: false冒泡  / true 捕获

注意点:
onXxx的属性, 不接收任何参数, 所以默认就是冒泡
attachEvent方法, 只能接收两个参数, 所以默认就是冒泡
*/

let oFDiv = document.querySelector(".father");
let oSDiv = document.querySelector(".son");

oFDiv.addEventListener("click", function () {
    console.log("father");
}, false);
oSDiv.addEventListener("click", function () {
    console.log("son");
}, false);

oFDiv.onclick = function () {
    console.log("father");
}
oSDiv.onclick = function () {
    console.log("son");
}

/*    
IE 6.0:
div -> body -> html -> document
其他浏览器:
    div -> body -> html -> document -> window
注意:
不是所有的事件都能冒泡,以下事件不冒泡:blur、focus、load、unload
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# 阻止事件冒泡

// 1.拿到需要操作的元素
var oFDiv = document.getElementById("father");
var oSDiv = document.getElementById("son");

// 2.注册事件监听
oFDiv.onclick = function () {
    console.log("father");
}
oSDiv.onclick = function (event) {
    event = event || window.event;
    // 注意点: stopPropagation方法只支持高级浏览器
    // event.stopPropagation();
    // event.cancelBubble = true; // 低级浏览器
    if (event.cancelBubble) {
        event.cancelBubble = true;
    } else {
        event.stopPropagation();
    }
    console.log("son");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 移入移出事件区别

    /*
    1.onmouseover和onmouseenter的区别
    onmouseover移入到子元素,父元素的移入事件也会被触发
    onmouseenter移入到子元素,父元素的移入事件不会被触发
    */
    /*
    2.onmouseout和onmouseleave的区别
    onmouseout移出到子元素,父元素的移入事件也会被触发
    onmouseleave移出到子元素,父元素的移入事件不会被触发
    */
    let oFDiv = document.querySelector(".father");
    let oSDiv = document.querySelector(".son");
    /*
    oFDiv.onmouseover = function () {
    console.log("father");
}
    oSDiv.onmouseover = function () {
    console.log("son");
}
    */
    /*
    oFDiv.onmouseenter = function () {
    console.log("father");
}
    oSDiv.onmouseenter = function () {
    console.log("son");
}
    */
    oFDiv.onmouseleave = function () {
        console.log("father");
    }
    oSDiv.onmouseleave = function () {
        console.log("son");
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 位置获取

/*
offsetX/offsetY: 事件触发相对于当前元素自身的位置
clientX/clientY: 事件触发相对于浏览器可视区域的位置
注意点: 可视区域是不包括滚动出去的范围的
pageX/pageY:     事件触发相对于整个网页的位置
注意点: 整个网页包括滚动出去的范围的
screenX/screenY: 事件触发相对于屏幕的位置
*/
var oDiv = document.getElementById("box");
oDiv.onclick = function (event) {
    event = event || window.event;
    console.log("offsetX", event.offsetX);
    console.log("offsetY", event.offsetY);
    console.log("clientX", event.clientX);
    console.log("clientY", event.clientY);
    console.log("----------------------");
    console.log("pageX", event.pageX);
    console.log("pageY", event.pageY);
    console.log(event.screenX);
    console.log(event.screenY);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

正则表达式

/*
1.什么是正则表达式?
正则表达式就是对字符串操作的一种逻辑公式

2.正则表达式的作用?
1.在字符串"查找"是否包含指定子串
2.从字符串中"提取"指定子串
3.对字符串中指定的内容进行"替换"
*/
//修饰符 i 不区分大小写
//      g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)
//      m 执行多行匹配

 -----------------------------
 // 1.字符串查找
/*
let str = "123abc456";
let index = str.indexOf("abc");
let index = str.lastIndexOf("abc");
let flag = str.includes("abc");
 */
// 2.字符串提取
/*
let str = "123abc456";
let startIndex = str.indexOf("a");
console.log(str.substr(startIndex, "abc".length));
 */
// 3.字符串替换
/*
let str = "123abc456";
str.replace("abc", "it666");
 */
 ----------------------
 // 1.利用正则表达式匹配(查找)
/*
let str = "123abc456";
// 1.创建一个正则表达式对象
// 2.指定匹配的规则
// 注意点: 默认情况下在正则表达式中是区分大小写的
let reg = new RegExp("A", "i");
let res = reg.test(str);
console.log(res);
 */
/*
let str = "abc2020-1-11def";
// 通过构造函数创建正则表达式对象
// let reg = new RegExp("\\d{4}-\\d{1,2}-\\d{1,2}");
// 通过字面量来创建正则表达式对象
let reg = /\d{4}-\d{1,2}-\d{1,2}/;
let res = reg.test(str);
console.log(res);
 */
// 2.通过正则表达式提取符合规则的字符串
/*
let str = "abc2020-1-11def2019-11-11fdjsklf";
// 注意点: 默认情况下在正则表达式中一旦匹配就会停止查找
let reg = /\d{4}-\d{1,2}-\d{1,2}/g;
let res = str.match(reg);
console.log(res);
console.log(res[0]);
console.log(res[1]);
 */
// 3.通过正则表达式替换符合规则的字符串
let str = "abc2020-1-11def2019-11-11fdjsklf";
let reg = /\d{4}-\d{1,2}-\d{1,2}/g;
let newStr = str.replace(reg, "it666");
console.log(str);
console.log(newStr);

----------------------
 <!--
常用正则表达式合集:
验证数字:^[0-9]*$
验证n位的数字:^\d{n}$
验证至少n位数字:^\d{n,}$
验证m-n位的数字:^\d{m,n}$
验证零和非零开头的数字:^(0|[1-9][0-9]*)$
验证有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
验证有1-3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
验证非零的正整数:^\+?[1-9][0-9]*$
验证非零的负整数:^\-[1-9][0-9]*$
验证非负整数(正整数 + 0^\d+$
验证非正整数(负整数 + 0^((-\d+)|(0+))$
验证长度为3的字符:^.{3}$
验证由26个英文字母组成的字符串:^[A-Za-z]+$
验证由26个大写英文字母组成的字符串:^[A-Z]+$
验证由26个小写英文字母组成的字符串:^[a-z]+$
验证由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
验证由数字、26个英文字母或者下划线组成的字符串:^\w+$
验证用户密码:^[a-zA-Z]\w{5,17}$ 正确格式为:以字母开头,长度在6-18之间,只能包含字符、数字和下划线。
验证是否含有 ^%&',;=?$\" 等字符:[^%&',;=?$\x22]+
验证汉字:^[\u4e00-\u9fa5],{0,}$
验证Email地址:^\w+[-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
验证InternetURL:^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ ;^[a-zA-z]+://(w+(-w+)*)(.(w+(-w+)*))*(?S*)?$
验证电话号码:^(\d3,4|\d{3,4}-)?\d{7,8}$:--正确格式为:XXXX-XXXXXXXXXXX-XXXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXX。
验证身份证号(15位或18位数字):^\d{15}|\d{}18$
验证一年的12个月:^(0?[1-9]|1[0-2])$ 正确格式为:“01-09”和“1”“12”
验证一个月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$    正确格式为:0109131。
整数:^-?\d+$
非负浮点数(正浮点数 + 0):^\d+(\.\d+)?$
正浮点数   ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
非正浮点数(负浮点数 + 0^((-\d+(\.\d+)?)|(0+(\.0+)?))$
负浮点数  ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数  ^(-?\d+)(\.\d+)?$
--> 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
Last Updated: 3/30/2022, 4:21:26 PM