DOM基础(1)

144 阅读8分钟

JavaScript的组成

JavaScript由ECMAScript,和Web APIs(DOM和BOM)组成。
ECMAScript是语法标准。
DOM是文档对象模型,是一套操作页面元素的API。
BOM是浏览器对象模型,是操作浏览器功能的API,通过BOM可以操作浏览器窗口,比如:弹出框,控制浏览器跳转,获取分辨率等等。
学习网站MDN:developer.mozilla.org/zh-CN/docs/…

DOM的概念

文档对象模型(Dbcument0bjectMode巪简称DOM),是W3C组织推荐的处理可扩展标 记语言的标准编程接口。它是一种与平台和语言无关的应用程序接口(API),它可以动态地访问程序和脚本,更新其内容、结构和www文档的风格(目前,HTML和XML文档是通过说明部分定义的)。文档可以进一步被处理,处理的结果可以加入到当前的页面。DOM是一种基于树的API文档,它要求在处理过程中整个文档都表示在存储器中。

DOM又称为文档树模型,如下图。

  • 文档:一个网页可以称为文档
  • 节点:网页中的所有内容都是节点(标签、属性、文本、注释等)
  • 元素:网页中的标签
  • 属性:标签的属性

DOM 经常进行的操作:

  • 获取元素
  • 对元素进行操作(设置其属性或调用其方法)
  • 动态创建元素
  • 事件(什么时机做相应的操作)

DOM 获取页面元素

DOM有很多种获取页面元素的方法。下面一一介绍。

根据id获取元素

方法:调用document对象的getElementById方法。
返回的是元素对象。

  • 注意1:由于id名具有唯一性,部分浏览器支持直接使用id名访问元素,但不是标准方式,不推荐使用。
  • 注意2:代码执行顺序,如果js在html结构之前,会导致结构未加载,不能获取对应id的元素。
<p id="para">text0</p>
<p id="para">text1</p>
<p id="box">text2</p>
<p>text3</p>
<p>text4</p>
<script>
  // 根据 id 获取元素
  var para = document.getElementById("para");
  // console.log(typeof para);
  // 补充:在控制台打印具体的对象
  // console.dir(para);
  para.style.background = "pink";
  // 代码书写顺序:js 中获取元素时,必须保证元素已经在浏览器中渲染成功
  // 需要将 js 的代码写在 html 结构之后
  // box.style.background = "blue"; 不推荐直接使用 id 名
</script>

根据标签名获取元素

方法:调用document对象的getElementsByTagName方法。
返回值:同名的元素对象组成的数组HTMLCollection。

  • 注意1:操作数据时需要按照操作数组的方法进行。
  • 注意2:getElementsByTagName方法内部获取的元素是动态增加的。
// 通过标签名获取元素
var ps = document.getElementsByTagName("p")
console.log(ps);
// HTMLCollection  html 元素组成的集合 伪数
// 遍历数组
for (var i = 0 ; i <= ps.length - 1; i++) {
  // 输出每一项
  console.log(ps[i]);
}
ps[0].style.background = "pink";

在元素对象内部获取标签元素

获取的元素对象内部,本身也可以调用根据标签获取元素方法,例如div元素对象也可以调用getElementsByTagName方法。
目的:缩小选择元素的范围,类似css中的后代选择器。

var box1 = document.getElementById("box1");
// 我们习惯将连续调用方式拆开书写
var ps1 = box1.getElementsByTagName("p");
console.log(ps1);

根据name获取元素

方法:调用document对象的getElementsByName方法。
参数:字符串类型的name属性值。
返回值:name属性值相同的元素对象组成的数组。
不建议使用:在IE和0pera中有兼容问题,会多选中id属性值相同的元素。

// 通过标签的 name 属性获取元素
var ages = document.getElementsByName("age");
// NodeList  节点列表集合  类数组
// 获取的元素也是动态增加的

根据类名获取元素

方法:调用document对的getElementsByClassName方法。 参数:字符串类型的class属性值。 返回值:class属性值相同的元素对象组成的数组。 浏览器兼容问题:不支持IE8及以下的浏览器

// 获取 id 为 box1 的元素对象
var box1 = document.getElementById("box1");
// 元素对象内部也可以调用 getElementsByClassName 方法
var paras1 = box1.getElementsByClassName("para");

根据选择器获取元素

方法1:调用document对象的querySelector方法,通过css中的选择器去选取第一个符合条件的标签元素。
方法2:调用document对象的querySelectorAll方法,通过css中的选择器去选取所有符合条件的标签元素。
参数:字符串类型的css中的选择器。
浏览器兼容问题:不支持IE8以下的浏览器

// 在结构之后使用 选择器 选取方法
var para = document.querySelector("#box1 .para");
console.log(para);
var paras = document.querySelectorAll("#box1 .para");
console.log(paras);

总结

掌握,没有兼容问题

  • getElementByid
  • getElementsByTagName 了解
  • getElementsByName
  • getElementsByClassName
  • querySelector
  • querySelectorAll

事件

事件:在什么时候做什么事
执行机制:触发--响应机制
绑定事件(注册事件)三要素:
1、事件源:给谁绑定事件
2、事件类型:绑定什么类型的事件click单击
3、事件函数:事件发生后执行什么内容,写在函数内部

事件监听

JavaScript解析器会给有绑定事件的元素添加一个监听,解析器会一直监测这个元素,只要触发对应的绑定事件,会立刻执行事件函数。
常用的鼠标事件类型

  • onclick 鼠标左键单击触发
  • ondblclick 鼠标左键双击触发
  • onmousedown 鼠标按键按下触发
  • onmouseup 鼠标按键放开时触发
  • onmousemove 鼠标在元素上移动触发
  • onmouseover 鼠标移动到元素上触发
  • onmouseout 鼠标移出元素边界触发

常用事件监听方法

  • 方法1:绑定HTML元素属性。
// 获取元素
<input type="button" id="btn" value="点击有惊喜" onclick="alert('点我做什么?')">
  • 方法2:绑定DOM对象属性。常用。
// 获取元素
var btn = document.getElementById("btn");
// 添加绑定事件
btn.onclick = function () {
    // 定义的是事件被触发后要做的事情
    alert("点我干嘛?");
};
<input type="button" id="btn" value="点击有惊喜" onclick="alert('点我做什么?')">

DOM元素属性操作

非表单元素的属性操作

  • 例如:href、title、id、src等。
  • 调用方式:元素对象打点调用属性名,例如obj.href
  • 注意:部分的属性名跟关键字和保留字冲突,会更换写法。 class→className
    for→htmlFor
    rowspan→rowSpan
<a href="http://www.baidu.com" title="跳转到百度页面" id="link">跳转</a>
<img src="images/a.jpg" alt="美女" class="pic" id="pic">
<script>
    // 获取元素
    var link = document.getElementById("link");
    var pic = document.getElementById("pic");
    // 调用元素对象的属性,从而操作 HTML 中标签的属性
    console.log(link.href);
    console.log(link.title);
    console.log(link.id);
    console.log(pic.src);
    console.log(pic.alt);
    console.log(pic.className);
    // 等号赋值,值必须是字符串类型的
    pic.src = "images/b.jpg";
</script>

点击按钮切换图片案例

<input type="button" value="点击" id="btn"><br>
<img src="images/a.jpg" id="pic">
<script>
  // 获取元素
  var btn = document.getElementById("btn");
  var pic = document.getElementById("pic");
  // 通过一个变量作为判断条件,变量值为 1,认为加载的是 a 图片,
  // 如果为 2 ,认为加载的是 b 图片
  var num = 1;
  // 给按钮添加点击事件
  btn.onclick = function () {
    // 给图片换 src 的属性值
    // 通过 if 语句判断,如果是 a 图片,就换成 b 图片,反之换成 a 图片
    if (num === 1) {
      pic.src = "images/b.jpg";
      // 数字要对应发生变化
      num = 2;
    } else {
      pic.src = "images/a.jpg";
      num = 1;
    }
  };
</script>

点击按钮显示或隐藏元素

先书写样式

<style>
  * {
    margin: 0;
    padding: 0;
  }
  div {
    width: 200px;
    height: 200px;
    background-color: pink;
  }
  .hide {
    display: none;
  }
  .show {
    display: block;
  }
</style>

再在body中书写js事件。

<input type="button" value="点击隐藏" id="btn">
<div id="box"></div>
<script>
  // 获取元素
  var btn = document.getElementById("btn");
  var box = document.getElementById("box");
  // 点击按钮,让 div 显示或隐藏
  // box.style.display = "none";//一般不用该方法
  btn.onclick = function () {
    // 元素 div 当前是显示的,需要让他隐藏
    // 根据 按钮 的 value 值进行条件判断
    if (btn.value === "点击隐藏") {
      box.className = "hide";
      btn.value = "点击显示";
    } else {
      box.className = "show";
      btn.value = "点击隐藏";
    }
    
  };
</script>

事件函数内部的this

在事件函数内部 有一个 this ,指向事件源
区分一下不同函数内部 this 的指向
普通函数 -> window 对象
构造函数 -> 指向的是生成的实例对象
对象的方法 -> 指向的是对象本身
事件函数 -> 指向的是事件源

btn.onclick = function () {
  if (this.value === "点击隐藏") {
    box.className = "hide";
    this.value = "点击显示";
  } else {
    box.className = "show";
    this.value = "点击隐藏";
  }      
};

批量绑定事件

<div id="imagegallery">
    <a href="images/1.jpg" title="美女A">
        <img src="images/1-small.jpg" width="100px" alt="美女1" />
    </a>
    <a href="images/2.jpg" title="美女B">
        <img src="images/2-small.jpg" width="100px" alt="美女2" />
    </a>
    <a href="images/3.jpg" title="美女C">
        <img src="images/3-small.jpg" width="100px" alt="美女3" />
    </a>
    <a href="images/4.jpg" title="美女D">
        <img src="images/4-small.jpg" width="100px" alt="美女4" />
    </a>
</div>
<div style="clear:both"></div>
<img id="image" src="images/placeholder.png" alt="" width="450px" />
<p id="des">选择一个图片</p>
<script>
    // 1.获取元素
    var imagegallery = document.getElementById("imagegallery");
    var links = imagegallery.getElementsByTagName("a");
    var image = document.getElementById("image");
    var des = document.getElementById("des");
    // 2.遍历数组,添加点击事件
    for (var i = 0 ; i <= links.length - 1 ; i++) {
        links[i].onclick = function () {
            // alert("aaa");
            // 3.更改 image 内部的 src 属性值
            // this 关键字指代的是触发事件的真正事件源
            image.src = this.href;
            // 4.更改 des 内部的文字内容
            des.innerText = this.title;
            // 5.取消 a 标签的默认跳转效果
            return false;
        };
    }
    // for 循环内部添加的绑定事件,在触发时,所有的批量添加的事件已经成功,触发事件时都是在循环结
    // 批量绑定的事件的事件函数内部如果有 变量 i,要注意,函数执行时已经是在循环结束后
    // 循环内部定义的变量是一个全局变量,在循环后执行的 i 变量的值是 i 跳出循环时的值
    // image.src = links[i].href;
    // console.log(i);
</script>

获取标签内部内容的属性

获取标签内部内容的属性有两个:innerHTML和innerText。

  • innerHTML属性,在获取标签内部内容时,如果包含标签,获取的内容会包含标签,获取的内容包括空白换行等。
  • innerText属性,在获取标签内部内容时,如果包含标签,获取的内容会去掉标签,获取的内容会用单个空格代替换行和缩进等空白。
    还可以通过两个属性给双标签内部去更改内容:
  • innerHTML设置属性值,有标签的字符串,会按照HTML语法中的标签加载。
  • innerText设置属性值,有标签的字符串,会按照普通的字符加载。 对比使用场景:
  • innerText:在设置纯字符串时使用。
  • innerHTML:在设置有内部子标签结构时使用
<div id="box">
  这是一个 div 标签
  <span>这是一个 span 标签</span>
</div>
<script>
  // 获取元素
  var box = document.getElementById("box");
  // 打印 box 对象
  console.dir(box);
  // 调用标签内部内容
  console.log(box.innerHTML);
  console.log(box.innerText);
  // 设置标签内部的内容
  // box.innerHTML = "<h2>hello JS</h2>";
  // box.innerText = "<h2>hello JS</h2>";
</script>

点开打印出的box结果如下:

表单元素属性操作

表单元素属性:

  • value用于大部分表单元素的内容获取(option除外)
  • type可以获取input标签的类型(输入框或复选框等)
  • disabled禁用属性
  • checked复选框选中属性
  • selected下拉菜单选中属性 注意:在DOM中元素对象的属性值只有一个时,会被转成布尔值显示。 例如:txt.disabled=true。
<input type="button" value="按钮" id="btn"><br>
<input type="text" id="txt">
<select id="list">
  <option value="beijing">北京</option>
  <option value="shanghai">上海</option>
</select>
<script>
  // 获取元素
  var btn = document.getElementById("btn");
  var txt = document.getElementById("txt");
  var list = document.getElementById("list");
  var opts = list.getElementsByTagName("option");
  
  // value 属性
  console.log(btn.value);
  console.log(txt.value);
  console.log(opts[0].value);
  console.log(opts[0].innerHTML);
  // 更改 input 标签的 value
  btn.value = "点击";
  txt.value = "请输入内容"
  // 表单元素特有的一些属性,属性名和属性值是一致的
  // console.log(txt.disabled);
  btn.disabled = true;
</script>

验证表单输入

<input type="text" id="name"><br>    
<input type="text" id="pw"><br>
<input type="button" id="btn" value="提交">
<script>
    // 检测用户名是否是3-6位,密码是否是6-8位,如果不满足要求高亮显示文本框
    // 1.获取元素
    var btn = document.getElementById("btn");
    
    // 2.给按钮添加点击事件,然后判断位数是否足够
    btn.onclick = function () {
        // 在事件触发后,去获取对象,内部的数据才是最新
        var userName = document.getElementById("name");
        var pw = document.getElementById("pw");
        // 用户名位数是否在 3-6 位,不满足需要高亮显示
        if (userName.value.length < 3 || userName.value.length > 6) {
            userName.className = "bg";
            return;
        } else {
            userName.className = "";
        }
        // 密码的位数必须在 6-8 位之间,否则高亮显示
        if (pw.value.length < 6 || pw.value.length > 8) {
            pw.className = "bg";
            return;
        } else {
            pw.className = "";
        }
        // 提交数据
        console.log("提交数据");
    };  
</script>

随机设置下拉菜单选中项

<input type="button" value="选择" id="btn">
<br>
<select id="food">
    <option>烤肉</option>
    <option>拉面</option>
    <option>麻辣烫</option>
    <option>小龙虾</option>
    <option>火锅</option>
    <option>外卖</option>
</select>
<script>
    // 1.获取元素
    var btn = document.getElementById("btn");
    var food = document.getElementById("food");
    var opts = food.getElementsByTagName("option");
    // 2.给按钮添加点击事件
    btn.onclick = function () {
        // 3.随机选择一个 option
        // 每次点击需要获取一个 opts 数组的随机下标
        // Math.random()   [0,1)
        // Math.random()*6   [0,6)
        var n = Math.floor(Math.random() * opts.length);
        // console.log(n);
        // 设置对应的随机项的属性
        opts[n].selected = true;
    };
</script>

搜索文本框案例

设置样式

<style>
  .gray {
    color: gray;
  }
  .black {
    color: black;
  }
</style>

绑定事件

<input type="text" class="gray" value="请输入搜索关键字" id="txtSearch">
<input type="button" value="搜索" id="btnSearch">
<script>
  // 获取元素
  var txtSearch = document.getElementById("txtSearch");
  // 1.获得焦点时,可以使用一个 onfocus,如果文本框内容是默认 请输入搜索关键字,
  // 需要清空文字,让文字加载黑色
  txtSearch.onfocus = function () {
    // 判断是否是默认的提示文字
    if (this.value === "请输入搜索关键字") {
      this.value = "";
      this.className = "black";
    }
  };
  // 2.失去焦点时,可以使用一个 onblur,如果文本框内容为空,
  // 需要改为默认提示内容 请输入搜索关键字,让文字颜色变为灰色
  txtSearch.onblur = function () {
    // 如果用户输入的内容正好与默认提示文本相同,失去焦点时,也应该让文字颜色变为灰色
    // 判断内容是否为空
    if (this.value === "" || this.value === "请输入搜索关键字") {
      this.value = "请输入搜索关键字";
      this.className = "gray";
    }
  };
</script>

全选和反选

DOM操作之-全选和反选案例

自定义属性操作

因为自定义属性,类型大小都未知,所以无法提前封装进元素对象,也就无法像操作自有属性一样使用“元素对象.属性名”来操作。

  • getAttribute(name)获取标签行内属性
  • setAttribute(name, value)设置标签行内属性
  • removeAttr(name)移除标签行内属性
  • 与element.属性的区别:上述三个方法用于获取任意的行内属性,包括自定义的属性。
<div id="box" age="18" sex="male">小明</div>
<script>
  // 获取元素
  var box = document.getElementById("box");
  // 元素自有属性
  console.log(box.id);
  // 元素自定义的新属性不能用点语法直接调用
  // 可以调用元素对象的获取自定义属性的方法
  console.log(box.getAttribute("age"));
  console.log(box.getAttribute("sex"));
  // 也可以调用自有的属性
  console.log(box.getAttribute("id"));
  // 设置属性,添加新的自定义属性或者自有属性
  box.setAttribute("age","20");
  box.setAttribute("city","Beijing");
  // 传的参数不需要进行属性名的修改
  box.setAttribute("class","demo");
  // 移除属性
  box.removeAttribute("age");
  box.removeAttribute("class");
</script>

style样式属性基本操作

  • 使用style属性方式设置的样式显示在标签行内。
  • element.style属性的值,是所有行内样式组成的一个样式对象。
  • 样式对象可以继续点语法调用或更改css的行内样式属性,例如width、height等属性。
  • 注意1:类似background-color这种复合属性的单一属性写法,是由多个单词组成的,要修改为驼峰命名方式书写backgroundColor。
  • 注意2:通过样式属性设置宽高、位置的属性类型是字符串,需要加上px等单位。

PS: 每次写获取元素对象的命令太长,为了简化书写可以做如下操作。

  1. 将获取对象函数再封装成函数my$(id),放入common.js文件,将来方便调用。下面是common.js中的内容。
// 定义一个获取元素的函数
function my$(id) {
  return document.getElementById(id);
}
  1. 在html文件中引用common.js,并调用my$(id),最后更改样式
<style>
    .bg{
        background-color: pink;
    }
</style>
<script src="common.js"></script>

调用并更改样式

// 获取元素        
var btn = my$("btn");
var box = my$("box");
// console.log(btn);
// 1.更改类名的方式去更改样式
// 2.根据对象的 style 属性去操作样式
console.log(btn.style);
// 元素对象的 style 属性的值是一个行内样式组成对象,
// 对象内部封装了所有的行内的样式属性及属性值
// 元素的样式属性对象可以继续打点调用,获取或设置相关的行内样式属性
console.log(box.style);
console.log(box.style.width);
// 注意:如果使用的 css 属性名是复合属性的单一属性,需要更改为驼峰命名法
console.log(box.style.backgroundColor);
box.style.width = "200px";

className 类名属性操作

修改元素的className属性相当于直接修改标签的类名。
如果需要修改多条css样式,可以提前将修改后的样式设置到一个类选择器中,后续通过修改类名的方式,批量修改css样式。
设置样式类:

.cls {
  width: 100px;
  height: 100px;
  background-color: pink;
}

修改样式:

<input type="button" value="按钮" id="btn">
<div id="box">文字</div>
<script>
    // 问题:实际工作中我们应该选择哪种方法?
    // 获取元素
    var btn = my$("btn");
    var box = my$("box");
    // 给按钮添加事件
    btn.onclick = function () {
      // 1.通过更改类名
      // box.className = "cls";
      // 2.通过元素对象的 style 属性进行设置
      box.style.width = "100px";
      box.style.height = "200px";
      box.style.backgroundColor = "yellow";
    };
</script>

开关灯案例

<input type="button" value="关灯" id="btn">
<script src="common.js"></script>
<script>
  // 获取元素
  var btn = my$("btn");
  // console.log(btn);
  // 定义一个判断变量,true 表示开灯状态,false 表示关灯状态
  // var isOpen = true;
  // 点击事件,控制 body 的背景
  btn.onclick = function () {
    // 开灯时,需要点击后让它关灯并切换文字为 开灯
    // 直接使用 btn 的 value 值进行判断
    if (this.value === "关灯") {
      document.body.style.backgroundColor = "black";
      this.value = "开灯";
    } else {
      document.body.style.backgroundColor = "white";
      this.value = "关灯";
    }
  };
</script>

显示二维码案例

设置样式

<style>
    .box {
        width: 50px;
        height: 50px;
        background: url(images/bgs.png) no-repeat -159px -51px;
        position: fixed;
        right: 10px;
        top: 40%;
    }
    .erweima {
        position: absolute;
        top: 0;
        left: -150px;
    }
    .box a {
        display: block;
        width: 50px;
        height: 50px;
    }
    .hide {
        display: none;
    }
    .show {
        display: block;
    }
</style>

设置html骨架,并绑定修改样式事件

<div class="box" id="box">
    <div class="erweima hide" id="er">
        <img src="images/456.png" alt=""/>
    </div>
</div>
<script src="common.js"></script>
<script>
    // 获取元素
    var box = my$("box");
    var er = my$("er");
    // 给 box 添加鼠标移上事件 onmouseover ,添加鼠标离开事件 onmouseout
    box.onmouseover = function () {
        // 让子级元素进行显示,就是将 hide 改为 show
        // er.className = "erweima show";
        er.className = er.className.replace("hide","show");
    };
    box.onmouseout = function () {
        // 让子级元素进行隐藏,就是将 show 改为 hide
        // er.className = "erweima hide";
        er.className = er.className.replace("show","hide");
    };
</script>

排他思想-文本框高亮显示案例

文本框高亮方便用户辨识输入。

<input type="text"><br>
<input type="text"><br>
<input type="text"><br>
<input type="text"><br>
<input type="text"><br>
<input type="text"><br>
<input type="text"><br>
<button id="btn">按钮</button>    
<script>
    // 获取元素
    var txts = document.getElementsByTagName("input");
    // 添加批量的获取焦点事件
    for (var i = 0 ; i < txts.length ; i++) {
        // 排他思想:1.排除其他 2.保留自己         
        // 给每一个input标签添加获取焦点事件
        txts[i].onfocus = function () {
            // 排除其他的方法:将所有的项包含自己都设置为默认样式
            // 遍历数组,让所有的样式恢复默认
            for (var j = 0 ; j < txts.length ; j++) {
                txts[j].style.backgroundColor = "";
            }
            // 设置元素自己高亮显示
            // 保留自己的特殊样式
            // this 指代事件源自己
            this.style.backgroundColor = "yellow";
        };
    }
</script>

表格隔行变色和高亮显示

DOM操作之-表格隔行变色和高亮显示案例

tab切换案例

DOM操作之-tab切换案例