这里写目录标题
DOM节点
node 是节点的意思
我们的页面是由节点组成的,每一个组成部分都是一个节点。
节点的分类:
元素节点 html标签 img body input div
文本节点 文字部分 (空格,换行也算)
属性节点 标签内的属性(比如id,class名是名不含里面的值)
注释节点
1.document
页面中最大的节点,有且只有一个。不属于元素节点,是页面中所有节点的容器。 根节点。
2.html
页面中最大的元素节点。根元素节点。
3.元素节点
html标签等
4.文本节点
每一段文本内容都是一个文本节点
包含 换行 和 空格
一般来说作为元素节点的子节点存在。
5.属性节点:
属性节点不能单独存在,必须依赖于元素节点。
6.注释节点
页面中的注释,作为说明文本使用。
自定义获取元素节点方法
<script>
/
node 表示传入的节点,获取该节点的元素节点。
classStr 表示传入的classname ,通过classname匹配元素节点
/
function elementsByClassName(node,classStr){
// 1.获取node这个节点下面的所有子节点。
var nodes = node.getElementsByTagName("*");
// 2.存放符合条件的节点
var arr = [];
//3.遍历所有的子节点
for (var i = 0; i < node.length; i++) {
//4.判断子节点的class是否与传入的classStr相等
if(nodes[i].className === classStr){
//5.若相等,则将其放入数组中。
arr.push(nodes[i]);
}
}
return arr;
}
</script>
操作元素节点的属性
标签上的属性分类:
1.原生属性
2.自定义属性
3.H5 自定义属性
1.原生属性
语法:元素.属性名
修改/新增:
元素.属性名 = “值”
获取:
元素.属性名
【注意】class属性是例外,不能直接通过属性名获取,而是用className
2.自定义属性
不能直接使用 元素. 这个语法来获取。
三个方法去操作:
获取
getAttribute(“属性名”);
返回值:字符串
设置
setAttribute(“属性名”,“属性值”)
删除
removeAttribute(“属性名”)
【注意】这三个方法也可以操作原生属性
3.H5 自定义属性
每一个元素节点上都有一个属性:dataSet
里面包含了所有的H5自定义属性。
键值对结构: 例子;data-id =“idBox”
key:data-XXX xxx的内容。
value:属性值
获取:
元素.dataset.key
设置:
元素.dataset.key = “值”
删除
delete 元素.dataset.key
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function () {
var oDiv = document.getElementsByTagName("div")[0];
// 原生属性--------------------
//console.log(oDiv.id);//获取 到第一个div中这个id的值
//oDiv.id = "xin"; //对获取 到第一个div中的id值修改
//【注意】class属性是例外,不能直接通过属性名获取,而是用className
//console.log(oDiv.className);//获取 到第一个div中的class值
//oDiv.className="xin";//更改 class值
//自定义属性
//var ziding = oDiv.getAttribute("ab"); console.log(ziding)//获取 自定义属性属性值
//var shezhi = oDiv.setAttribute("ab", "wei");//更改 自定义属性的属性值 变为 ab="wei"
//var shanchu = oDiv.removeAttribute("ab" );//删除自定义的属性
//H5 自定义属性----------------------------------------------------------
oDiv.dataset.name="xin"//添加属性 div里面有一个dataset.name="xin"属性节点
// console.log( oDiv.dataset.name) ;//获取
//delete oDiv.dataset.name;//把上边添加属性节点删除
}
//dataset.name中的name是可以自己起名字的dataset.XXX
</script>
</head>
<body>
<div id="jiu" ab="nihao" class="jiu"></div>
</body>
这是dataset的进一步理解
<body>
<div getTime="20" data-index="2" data-list-name="andy">张三</div>
</body>
<script>
var div = document.querySelector('div');
console.log(div);
// setAttribute()设置属性节点 getAttribute()获取属性节点
/* div.setAttribute('data-time', 30);//新建了一个自定义的属性并填值
console.log(div.getAttribute('getTime'));//20
console.log(div.getAttribute('data-index'));//2
console.log(div.getAttribute('data-list-name'));//andy*/
// 1.h5新增的获取自定义属性的方法 它只能获取data-开头的
// 2.dataset 是一个集合里面存放了所有以data开头的自定义属性
// console.log(div.dataset);//{
index: "2", listName: "andy"}
/*console.log(div.dataset.index);//2
console.log(div.dataset['index']);//2(这是另一种写法)*/
// 3.如果自定义属性里面有多个-链接的单词,我们获取的时候采取 驼峰命名法
/* console.log(div.dataset.listName); //andy
console.log(div.dataset['listName']); //andy*/
//4.设置自定义属性的属性值 格式: 元素.dataset.key="值"
/* div.dataset.index = "xin";
console.log(div.getAttribute('data-index')); //获取到data-index="xin"
// div.dataset.listName = "xin";//这样也是对自定义属性值进行了更改*/
//5.删除 格式: delete 元素.dataset.key
/*delete div.dataset.index
console.log(div);//输出我们可以看到data-index="2" 被删除了*/
</script>
操作元素的类名
1。按照原生属性的方式来操作
获取:
元素.className
设置:
元素.className = “值”
追加:
元素.className += " 值";
【注意】 追加时,值的前面要加一个空格。
删除:
1.重新设置一遍。
2.
2.1 获取classname属性值、
2.2 按照空格去分割字符串
2.3 遍历数组,将要删除的字符串删除
2.4 数组的join方法
2.H5标准给我们一个API
元素节点都有一个属性叫做:classList
里面包含了所有的class值。
获取:
元素.classList 获取class值的集合。
想要获取单个,使用下标。
新增:
元素.classList.add(“新增的类名”)
删除:
元素.classList.remove(“删除的类名”)
替换:
元素.classList.replace(“旧类名”,“新类名”) ;
toggle() 切换
语法:元素.classList.toggle(类名)
当元素拥有这个类名时,将类名删除
当元素没有这个类名时,将类名添加
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function () {
var bDiv = document.getElementsByTagName("div")[0];//获取到第一个div,并起名为bDiv
// var huoqu=bDiv.className;//获取到这个类名,并起名为huoqu
//var gai = bDiv.className = "xin";//更改类名
//var jia = bDiv.className += " xin";//添加类名,后加的这个要有一个空格
//var del= bDiv.className = "";重新设置一遍为空删除方法
//H5标准----------------------------------------------------------------------------------------
//var huoqu=bDiv.classList;//获取所有的class值
console.log(huoqu);//box a
//var jia = bDiv.classList.add("d");//添加一个类名
//var shanchu=bDiv.classList.remove("box");删除你指定的类名
//var tihuan = bDiv.classList.replace("box" , "zhao"); 替换:元素.classList.replace("旧类名","新类名") ;
// var huan=bDiv.classList.toggle("a");当有这个类名时把它删除。没有时添加
}
</script>
</head>
<body>
<div class="box a"></div>
</body>
</html>
操作元素节点中的内容
1.innerHTMl
获取元素节点中除了本身的标签外,所有的HTML代码。
获取:
元素.innerHTML
设置:
元素.innerHTMl = “新的内容”
【注意】 innerHTML 会覆盖原有的内容,而且会解析其中的标签。
2.innerText
获取元素节点中的文本内容,会覆盖原有的内容,不会解析内容中的标签。
获取:
元素.innerText
设置:
元素.innerText = “新的内容”;
3.value
主要使用在表单元素中。
操作表单元素节点的value属性。
获取:
表单元素节点.value
设置:
表单元素节点.value = “值”
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function () {
var box = document.getElementById("box");
// box.innerHTML="<h1>我是新的innerHTML</h1>";
// box.innerText="<h1>我是新的innerHTML</h1>";
var inp = document.getElementById("inp");
inp.value = "赵宏伟";
}
</script>
</head>
<body>
<div id="box">我是div标签<br> </div>
<input type="text" id="inp">
</body>
</html>
函数的执行顺序
函数的执行
里面若涉及到了变量
在定义的时候不解析变量,而是按照变量名保存,
只有在函数调用时,才会解析变量
<script>
var num = 20;
function func(){
console.log(num);//输出是40
}
num = 40;
func();
</script>
this:(重要)
在函数中,this保存的是函数调用者的地址信息。
谁调用了当前的函数,this就表示谁。
this全局变量中指向window
单独使用 this,则它指向全局对象。
<script>
console.log(this);// Window
</script>
this在对象的方法中指向调用者
<script>
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a);//12(运行过程,是b调用了这个函数,然后去b里面找a)
}
}
}
o.b.fn();//这里的this指b
</script>
下面这个例子你可能会认为this为j,并不是,j只是给赋值
<script> var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a);//undefined (去window里面找a,找不到所以为未定义)
console.log(this);//window
}
}
}
// o.b.fn(); 放开这个, this就为b this.a就为12
var j = o.b.fn;
window.j();
</script>
this在事件绑定中,指向目标对象。
<body>
<div id="box"></div>
</body>
<script>
var box = document.getElementById("box");
box.onclick = function(){
console.log(this);//this指向为box
}
</script>
this在定时器处理函数中,指向window
<script>
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a);//undefined window里面找不到a,所以为未定义
console.log(this);//window
}
}
}
setTimeout(o.b.fn,0)
//setInterval(o.b.fn,1000)
</script>
强行改变this指向的方式
call()
格式:
函数名.call(obj,arg...);
/obj : 函数内部的this指向
/arg...:从第二个参数开始,为函数的参数。是一个一个的
而apply()的参数是一个数组
特点:立即执行当前函数。
<script>
function fn(x, y) {
console.log(x + y); //30
console.log(this); //this指向window
}
fn(10, 20)
</script>
<script>
function fn(x, y) {
console.log(x + y); //30
console.log(this); //this指向obj{}
}
var obj = {
}
fn.call(obj, 10, 20);
</script>
【注意】定时器处理函数或者事件处理函数不能用
<script>
function fn(){
console.log("我是延时函数");
}
var obj={
}
// setTimeout(fn,3000)//正常使用3s后执行
setTimeout(fn.call(obj),3000);//直接出现,延迟失效
</script>
apply()
格式:
/obj : 函数内部的this指向
/arr:一个数组或者伪数组,里面的每一个元素会依次传递给函数。
函数名.apply(obj,arr);
特点:立即执行当前函数。
<script>
function fn(x, y) {
console.log(x + y); //30
console.log(this); //this指向window
}
fn(10, 20)
</script>
-------------------------------------------------------------------------------
<script>
function fn(x, y) {
console.log(x + y); //30
console.log(this); //this指向obj{}这个空对象
}
fn(10, 20)
var obj = {
};
fn.apply(obj, [10, 20]);
</script>
【注意】定时器处理函数或者事件处理函数不能用
这是应用:可以以数组的形式给某些功能函数传参。
<script>
/*常规方法
var max = Math.max(10,5,30,-15,6);
console.log(max);//30*/
//apply()方法
var arr = [10, 5, 30, -15, 6, 40]
var max2 = Math.max.apply(null, arr);
console.log(max2);//40
</script>
面试题
求数组中的最大值 和 最小值
(上面提到,apply()传入的参数可以是一个数组,所以可以这样写)
let arr = [11, 34, 22, 45, 50]
js的解法:(后面es6中res还有新的写法)
let max = Math.max.apply(null, arr)
let min = Math.min.apply(null, arr)
bind()
格式:
/obj : 函数内部的this指向
/arg:从第二个参数开始,依次为函数传递参数。
函数名.apply(obj,...arg);
特点
不会立即执行函数,会返回一个新的函数,该函数内部的this指向为传入的对象。
<!-- <script>
function fn(x,y){
console.log(x+y);//30
console.log(this);// this指向window
}
fn(10,20);
</script> -->
<script>
function fn(x, y) {
console.log(x + y);// 30
console.log(this);//this指向obj{}
}
var obj = {
}
var res = fn.bind(obj, 10, 20);
res(); //调用
</script>
把这个图记住就是区别:
面试题,call() apply() 的区别:
call() apply()
-
共同点
- 修改this指向,
- 调用执行函数
-
不同点:
参数的传递方式不同, call()参数是一一罗列;
apply()参数是以数组的形式传递
操作元素节点的样式
元素节点的样式:
样式:
行内
内嵌
外链
行内样式:
原生属性的方式获取
元素.style.样式的属性名
【注意】如果属性名是多个单词,第二个单词首字母大写,删除中划线。 比如背景颜色
该方法只能获取行内。
获取元素的有效样式
-
标准浏览器:
getComputedStyle(要获取样式的元素)
-
IE低版本:(IE8以下)
元素.currentStyle.样式属性名
例如: box.currentStyle.width
设置样式
语法:元素.style.样式名 = “值”;
<!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>
#box{
width: 200px;
}
</style>
<script>
window.οnlοad=function(){
var box = document.getElementById("box");
//该方法只能获取行内样式
console.log(box.style.height);//获取到宽
console.log(box.style.backgroundColor);//获取到背景色
//获取到有效样式-标准浏览器
console.log( getComputedStyle(box).width) ;//这样格式写
console.log( getComputedStyle(box)[width]) ;//或者这样格式写
// IE低版本-这样写
console.log( box.currentStyle.width);
//兼容写法
//node 要获取样式的元素节点 cssStyle 要获取样式的属性名
function getStyle(node,cssStyle){
return node.currentStyle?node.currentStyle[cssStyle]:getComputedStyle(node)[cssStyle];
}
}
</script>
</head>
<body>
<div id="box" style="height: 100px;background-color: blue;"></div>
</body>
</html>
获取元素节点的属性节点
属性节点:
获取元素节点的属性节点
元素.attributes
单个属性节点:
元素.attributes.getNamedItem(“属性名”);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var box = document.getElementById("box");
//获取box这个元素节点中的所有属性节点
console.log(box.attributes);//获取到id和class的值
//获取单个属性节点
console.log(box.attributes.getNamedItem("class"));//home 当class还有其他值时也会获取
}
</script>
</head>
<body>
<div id="box" class="home"></div>
</body>
</html>
通过节点关系获取节点
DOM节点不是孤立存在,我们可以通过节点之间的关系去获取他们。
节点的关系,是以属性的方式存在的。
获取父节点。
节点.parentNode
(IE支持parentElement和parentNode获取父节点,而firfox只能使用parentNode来获取父节点。
所以在JS中获取父节点是,推荐大家统一使用parentNode。)
获取兄弟节点
1.下一个节点
node.nextSibling
对于标准浏览器,标签,空文档,换行都属于节点。
IE低版本:指下一个元素节点。
2.下一个元素节点
node.nextElementSibling
下一个兄弟节点 = 节点.nextElementSibling||节点.nextSibling(保守写法)
3.上一个节点
node.previousSibling
4.上一个元素节点
node.previousElementSibling
获取单个子节点
1.第一个子节点
node.firstChild
2.获取第一个元素节点
node.firstElementChild
3.获取最后一个子节点
node.lastChild
4.获取最后一个元素节点
node.lastElementChild
获取所有子节点
1.获取所有子节点
语法:node.childNodes
返回的是子节点的伪数组(元素节点,文本节点,注释节点)
2.获取所有的元素子节点
语法:node.children
返回元素节点。使用最多的方法。
节点的属性
属性:事物的特征
nodeName: 节点名称
注释节点: #comment
文本节点: #text
元素节点: 大写的标签名
属性节点: 属性名
nodeType:节点类型
注释节点:8
文本节点:3
元素节点:1
属性节点:2
nodeValue:节点的值
注释节点:注释内容
文本节点:文本内容
元素节点:null
属性节点:属性值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function () {
var box = document.getElementById("box");
console.log(box.parentNode);// 元素节点div的父节点是body
console.log(box.nextSibling);//获取到下一个节点,空格换行也算 获取到空格换行是#text
console.log(box.nextElementSibling);//获取到下一个元素节点<p class="box">我是p标签</p>
// 不会出错的写法 下一个兄弟节点 = 节点.nextElementSibling||节点.nextSibling
//-----------------------------------------------------------
console.log(box.previousSibling);//获取到上一个节点,空格换行也算
console.log(box.previousElementSibling);//获取到上一个元素节点
//获取单个子元素节点-----------------------------------------------------
console.log(document.body.firstChild) //第一个子节点,空格换行也算
console.log(document.body.firstElementChild);//第一个子元素节点,包含h1中所有内容
//-------------------------------------------------------------
console.log(document.body.lastChild);//最后一个子节点,空格换行也算
console.log(document.body.lastElementChild);//最后一个子元素节点
//-------------------------------------------------------------
//console.log(document.body.childNodes);//获取body中所有的子节点输出的是伪数组(元素节点,属性,文本节点,注释节点)
//console.log(document.body.children);//获取body中所有的元素子节点
//-------------------------------------------------------------------------------------------
var firstChild = document.body.firstChild;//body中第一个节点 这里指的是<!-- 我是注释 -->
var sec = firstChild.nextSibling;第一个节点的下一个节点 这里指的是 纸短情长
var h1 = document.body.firstElementChild;//body中第一个元素节点 这里指的是 h1标签
var title = h1.attributes.getNamedItem("id");//直接选中h1属性节点 这里指的是id="title"
/*attributes 属性返回指定节点的属性集合 getNamedItem() 方法返回节点列表中指定属性名的值。*/
// console.log("注释节点:nodeName="+firstChild.nodeName);//#comment
// console.log("注释节点:nodeType="+firstChild.nodeType);//8
// console.log("注释节点:nodeValue="+firstChild.nodeValue);//注释内容 这里是 我是注释
// console.log("文本节点:nodeName="+sec.nodeName);//#text
// console.log("文本节点:nodeType="+sec.nodeType);//3
// console.log("文本节点:nodeValue="+sec.nodeValue);//文本内容 这里是 纸短情长
// console.log("元素节点:nodeName="+h1.nodeName);//H1 这里是 大写的标签名
// console.log("元素节点:nodeType="+h1.nodeType);//1
// console.log("元素节点:nodeValue="+h1.nodeValue);//null
console.log("属性节点:nodeName=" + title.nodeName);//属性名 这里是 id
console.log("属性节点:nodeType=" + title.nodeType);//2
console.log("属性节点:nodeValue=" + title.nodeValue);//属性值 这里是 title
}
</script>
</head>
<body>
<!-- 我是注释 -->纸短情长<h1 id="title">我是一级标题</h1>
<div id="box">我是div标签</div>
<p class="box">我是p标签</p>
</body>
</head>
</html>
未获取对应id的dom节点,可直接用id操作dom
<div id="app">
<div id="aaa">
</div>
</div>
//js代码
console.log(app);
console.log(aaa);
网上查询后发现了一点总结:
dom元素的id名称不和js内置属性或全局变量重名的话,该名称自动成为window对象的属性