关于DOM的高级事件请查看DOM的高级事件
W3C已经定义了一些系列的DOM接口,通过这些接口可以改变网页的内容、结构和样式
DOM把以上内容都看作对象
因为我们文档页面从上往下加载,所以先有标签,我们将js卸载标签下main
DOM在我们实际开发中主要用来操作元素
获取页面元素可以使用以下几种方法
使用getElementById()
方法可以获取带有ID的元素对象
id是大小写名敏感的字符串,代表了所要查找的元素的唯一ID
返回值:返回一个匹配到ID的DOM Element对象。若在文档中没有找到对象,则返回null
<div id="time">2021-7-21div>
<script>
var timer = document.getElementById('time');//document(文档),指在文档中选出该元素
console.log(timer);//2021-7-21
//console.dir()打印我们返回的元素对象,更好的查看里面的属性和方法
console.dir(timer)
script>
返回的是 获取过来元素对象的集合,以伪数组的形式存储
使用getElementsByTagName()
方法可以返回带有指定标签名的对象的集合
<ul>
<li>知否知否,应是绿肥红瘦1li>
<li>知否知否,应是绿肥红瘦2li>
<li>知否知否,应是绿肥红瘦3li>
<li>知否知否,应是绿肥红瘦4li>
ul>
<script>
var list = document.getElementsByTagName('li');
console.log(list);
console.log(list[0]);
script>
注意:
从父类中获取元素
element.getElementsByTagName('标签名')
伪数组不能作为父元素
父元素必须是单个对象(必须指明是哪个元素对象),获取的时候不包括父元素自己
<ul>
<li>知否知否,应是绿肥红瘦1li>
<li>知否知否,应是绿肥红瘦2li>
<li>知否知否,应是绿肥红瘦3li>
<li>知否知否,应是绿肥红瘦4li>
ul>
<ol>
<li>你li>
<li>我li>
ol>
要求:选取ol中的li
代码:
<script>
var ol = document.getElementsByTagName('ol');
for(var i = 0; i < ol.length; i++)
console.log(ol[i].getElementsByTagName('li'));
script>
类名获取
document.getElementsByClassName('类名')
找到的依旧是一个伪数组
选择器单个获取
document.querySelector('选择器')
根据指定的选择器返回第一个元素,不是一个伪类数组
选择器多个获取
document.querySelectorAll('选择器')
根据指定选择器返回全部的元素的集合,是一个伪数组
获取body元素
document.body
获取html元素
document.documentElement
JavaScript使我们有能力创建动态页面,而事件是可以被JavaScript侦测到的行为
简单理解:触发–响应机制
网页中的每一个元素都可以产生某些可以触发JavaScript的事件,例如,我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作
事件源:事件被触发的对象,比如:按钮
事件类型:如何触发,什么事件,比如鼠标点击(onclick)
事件处理程序:通过一个函数赋值的形式完成
<button id="btn">唐伯虎button>
<script>
var btn = getElementById('btn');
btn.onclick = function(){
alert('点秋香');
}
script>
事件源.事件类型 = function(){
事件处理程序
}
鼠标事件类型:
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获取鼠标焦点触发(焦点就是光标的位置) |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触动 |
JavaScript的DOM操作可以改变页面内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等
element.innerText
从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉
innerText不能识别html标签,所以在修改的时候不能加入html标签
<p>1589p>
<script>
function getDate(){
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
var day = date.getDay();
return '今天是' + 'year' + '年' + 'month' + '月' + 'dates' + '日' + arr[day];
}
var p = document.querySelector('p')
p.innerText =getDate();
script>
那么打开网页就显示当前的时间
element.innerHTML
可以识别html标签
起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行
<botton id='ldh'>刘德华botton>
<botton id='zxy'>张学友botton>
<img src="imges/ldh.jpg">
<script>
var ldh = document.getElementById('ldh');
var zxy = document.getElementById('zxy');
var img = document.querySelector('img');
zxy.onclic = function(){
img.src = 'imges/zxy.jpg';
}
ldy.onclick = function(){
img.src = 'imges/zxy.jpg';
}
script>
<img src="imges/s.gip">
<div>上午好div>
<script>
var img = querySelector('img');
var div = querySelector('div');
var date = new Date();
var hour = date.getHours();
if(hour < 12){
img.src = 'imges/s.gip';
div.innerText = '上午好';
}else if (hour <18){
img.src = 'imges/z.jpg';
div.innerText = '下午好';
}else if{
img.src = 'imges/w.jpg';
div.innerText = '晚上好';
}
script>
<button>按钮button>
<input type="text" value="输入内容">
<script>
var btn = document.querySelector('botton');
var input = document.querySelector('input');
btn.onclick = function(){
//input.innerText = '点击了';这个是普通标签使用的,但是表单标签不适用
input.value = '点击了';
//如果想要某个表单被禁用,不能再次点击,我们可以修改disable
btn.disable = true;//或者为this.disable = true;
}
script>
表单属性不在使用,可以将disable改为true
函数代码中的this指向函数的调用对象
DOCTYPE html>
<html>
<head>
<title>testtitle>
<style type="text/css">
.box{
width: 400px;
border-bottom: 5px solid #E7E3E3;
margin: 100px auto;
position: relative;
}
.box>input{
height: 30px;
width: 370px;
border: 0px;
outline: none;
}
img{
height: 10px;
width: 24px;
position: absolute;
top: 10px;
right: 10px;
}
style>
head>
<body>
<div class="box">
<input type="password" name="">
<img src="./img/01.jpg">
<script type="text/javascript">
var img = document.querySelector('img');
var input = document.querySelector('input');
var flag = 1;
img.onclick = function(){
if(flag == 1){
input.type = 'text';
flag = 0;
}else{
input.type = 'password';
flag = 1;
}
}
script>
div>
body>
html>
我们可以通过js修改元素的大小、颜色、位置等样式
1.element.style 行内样式操作
2.element.className 类名样式操作
注意:
<style>
div{
background-color:black;
}
style>
<html>
<div>div>
html>
<script>
var div = document.querySelector('div');
div.onclick = function(){
this.style.backgroundColor = 'purple';
}
script>
精灵图:就是一张图有一列的图标
在循环精灵图的时候,在css中要先有精灵图的url
在遍历的时候,图片的位置就是相当于在ps中的x,y轴中的位置,一般每个图标的大小都是一致的,所以方便遍历
<style>
li{
background:url(images/sprite.png) no-repeat;
}
style>
<script>
var lis = document.querySelectorAll('li');
for (var i = 0; i < lis.length; i++){
var index = i * 44;
lis[i].style.backgroundPosition = '0'+ '-' + index + 'px'
}
script>
案例分析:
首先表单需要2个新事件,获取焦点onfocus,失去焦点onblur
如果获得焦点,判断表单里面的内容是否为默认文字,如果为默认文字,就清空表单内容
如果失去焦点,判断表单内容是否为空,如果为空,则表单内容改为默认文字
DOCTYPE html>
<html>
<head>
<title>testtitle>
<style type="text/css">
input{
color: #999;
}
style>
head>
<body>
<div class="box">
<input type="text" name="" value="收集">
<script type="text/javascript">
var input = document.querySelector('input');
//获取焦点时
input.onfocus = function(){
if (input.value === '收集'){
input.value = '';
//将文字加深
this.style.color = '#333';
}
}
//失去焦点时
input.onblur = function(){
if (this.value === ''){
this.value = '收集';
//将文字变浅
this.style.color = '#999'
}
}
script>
div>
body>
html>
注意:
DOCTYPE html>
<html>
<head>
<title>nonetitle>
<style>
.change1{
background-color:red;
height:70px;
margin-top:90px;
}
.change2{
background-color:pink;
height:10px;
}
style>
head>
<body>
<div class="change1">div>
<script>
var div = document.querySelector('div');
div.onclick = function(){
this.className = 'change2';
}
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
div{
width: 600px;
margin: 100px auto;
}
.message{
display: inline-block;
font-size: 12px;
color: #999;
background: url(taobao.PNG) no-repeat;
padding-left: 25px;
}
.wrong{
color: red;
}
.right{
color: green;
}
style>
head>
<body>
<div class="register">
<input type="password" class="ipt">
<p class="message">请输入6~16位密码p>
div>
<script>
var ipt = document.querySelector('.ipt');
var message = document.querySelector('.message');
ipt.onblur = function(){
if(this.value.length <6 || this.value.length > 16)
{
message.className = 'message wrong';//增加class值 而不是粗暴的修改
message.innerHTML = '你输入的位数不对';
}else{
message.className = 'message right';
message.innerHTML = '你输入的位数正确';
}
}
script>
body>
html>
在修改class名的时候,在原来类名的基础上加一个,使一个元素拥有两个相同的属性和新加入类名的覆盖属性
如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法:
DOCTYPE html>
<html>
<head>
<title>换皮肤title>
<style type="text/css">
.imgLine{
margin: 500px auto;
padding-left:500px;
}
.imgLine>img{
width: 100px;
height: 100px;
}
body{
background-image: url('./img/01.jpg');
}
style>
head>
<body>
<div class="imgLine">
<img src="./img/01.jpg" class="firstImg">
<img src="./img/02.jpg" class="secondImg">
div>
<script type="text/javascript">
var img = document.querySelectorAll('img');
console.log(img);
for (let i = 0; i < img.length; i++){
img[i].onclick = function(){
console.log(this.src);
document.body.style.backgroundImage = 'url(' + this.src+ ')';
}
}
script>
body>
html>
案例分析
全选和取消全选做法:让下面所有的复选框的checked属性(选中状态)跟随全选按钮即可
当单选全部勾选的时候,全选的选框自动勾选,当失去个别单选选框的时候,全选选框失去勾选
DOCTYPE html>
<html>
<head>
<title>全选和单选title>
head>
<body>
<table border="1">
<thead>
<tr>
<th><input type="checkbox" name="choseAll" id="choseAll">th>
<th>商品th>
<th>价格th>
tr>
thead>
<tbody>
<tr>
<td><input type="checkbox" name="goodList">td>
<td>商品1td>
<td class="price">1000td>
tr>
<tr>
<td><input type="checkbox" name="goodList">td>
<td>商品2td>
<td class="price">20000td>
tr>
<tr>
<td><input type="checkbox" name="goodList">td>
<td>商品3td>
<td class="price">100td>
tr>
tbody>
table>
<button>确定button>
<a>最后总共消费0元a>
<script type="text/javascript">
var chose_all = document.getElementById('choseAll');
var inputList = document.getElementsByName('goodList');
var price = document.querySelectorAll('.price');
var submit = document.querySelector('button');
var result = document.querySelector('a');
//全选或者取消全选
chose_all.onclick = function(){
for (let i = 0; i < inputList.length; i++) {
inputList[i].checked = this.checked;
}
}
//单选对全选的影响
flag = false;
for (let i = 0; i < inputList.length; i++) {
inputList[i].onclick = function(){
for (let i = 0; i < inputList.length; i++) {
if(inputList[i].checked == true){
flag = true;
}else{
flag = false;
break;
}
}
chose_all.checked = flag;
}
}
submit.onclick = function(){
let sum = 0;
for (let i = 0; i < inputList.length; i++) {
if(inputList[i].checked == true){
sum += parseInt(price[i].innerText);
}
}
result.innerText = '最后总共消费' + sum + '元';
}
script>
body>
html>
自定义属性目的:为了保存并使用数据,有些数据可以保存到页面中而不用保存到数据库中
在H5规定中自定义属性data-
开头为属性名并且赋值
例如:
element.属性
<html>
<div id="demo">
哈哈哈哈
div>
html>
<script>
var div = querySelector('div');
console.log(div.id);
script>
element.getAttribute(‘属性’)
get得到获取attribute属性的意思
<html>
<div id="demo">
哈哈哈哈
div>
html>
<script>
var div = querySelector('div');
console.log(div.getAttribute('id'));
script>
区别:
获取所有自定义属性:
element.dataset
,返回的是一个集合
**如果自定义属性里面有多个-
连接的单词,此时我们使用驼峰命名法 **
<div data-index = "2" data-list-name = "andy">1div>
<script>
console.log(div.dataset);//返回的是一个集合
console.log(div.dataset['index']);//返回data-index的属性值
console.log(div.dataset.index);
console.log(div.dataset.listName);
script>
element.setAttribute('属性')
<html>
<div id="demo" index="1">
哈哈哈哈
div>
html>
<script>
var div = querySelector('div');
div.setAttribute('属性','值');
script>
element.removeAttribute('属性')
DOCTYPE html>
<html>
<head>
<title>title>
<link rel="stylesheet" type="text/css" href="./CSS/reset.css">
<style type="text/css">
.tabBox{
margin: 100px;
position: relative;
}
ul li {
float: left;
width: 100px;
height: 30px;
line-height: 30px;
text-align: center;
background-color: #fff;
border: 1px #bbb solid;
border-bottom: none;
cursor: pointer;
}
#tab_con{
position: absolute;
top: 31px;
}
.onclickStyle{
background-color: red;
color: #fff;
}
style>
head>
<body>
<div class="tabBox">
<ul id="tab">
<li class="onclickStyle">tab1li>
<li>tab2li>
<li>tab3li>
ul>
<div id="tab_con">
<div >aaaadiv>
<div style="display:none">bbbbdiv>
<div style="display:none">ccccdiv>
div>
div>
<script type="text/javascript">
var liList = document.querySelectorAll('ul>li');
var divList = document.querySelectorAll('#tab_con>div');
for (let i = 0; i < liList.length; i++) {
//注意此处不能使用var定义,var定义之后,i是全局变量,使tab栏内容无法出现
liList[i].onclick = function(){
for (let i = 0; i < liList.length; i++) {
liList[i].className = '';
divList[i].style.display = 'none';
}
this.className = 'onclickStyle';
divList[i].style.display = 'block';
}
}
script>
body>
html>
利用结点层级关系获取元素
一般地,节点至少拥有节点类型、节点名称、节点值这三个基本属性
我们实际开发中,节点操作主要操作的是元素节点
element.parentNode
<html>
<div class="box">
<span class="erweima">xspan>
div>
html>
在此代码中,div
和span
是父子关系
//选择器选择元素
var erweima = document.querySelector('.erweima');
var box = document.querySelector('.box');
//使用节点选择元素
var erweima = document.querySelector('.erweima');
var box = erweima.parentNode;
element.childNodes
element.children
注意:childNodes获得的是所有子节点,包含元素节点、文本结点等等;children是获取所有的子元素节点
<ul>
<li>1li>
<li>2li>
<li>3li>
<li>4li>
ul>
<script>
console.log(ul.childNodes);//NodeList(9)
console.log(ul.children)//HTMLCollection(4)
script>
ul下li的个数只有4个,但是集合中却出现了9个,这是因为 使用childNode选取的节点包括换行(文本节点),所以加起来总共有9个
如果需要使用childNodes选取所有元素节点,这就需要for循环
var ul = document.querySelector('ul');
for(let i = 0; i < ul.childNodes.length; i++){
if (ul.childNodes[i].nodeType == 1){
//ul.childNodes[i]是元素节点
console.log(ul.childNodes[i]);
}
}
子节点补充:
最后两个方法有兼容性问题,IE9以上才支持
element.nextSibling
返回当前元素的下一个兄弟节点(包括文本节点和元素节点)
element.previousSibling
返回当前元素的上一个兄弟节点(包括文本节点和元素节点)
element.nextElementSibling
返回当前元素下一个兄弟元素节点
element.previousElementSibling
返回当前元素上一个兄弟元素节点
document.createElement('tagName')
该方法创建由tagName指定的HTML元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们称为动态创建元素节点
node.appendChild(child)
node 父级 child子级
node.appendChild()方法将一个节点添加到指定父节点的节点列表末尾,类似于css中的after伪元素
var ul = document.querySelector('ul');
var li = document.createElement('li');//创建li元素
ul.appendChild(li);//将li元素放在ul下的列表末尾
node.insertBefore(child,指定元素)
该方法是将一个节点添加到父节点的指定子节点的 前面,类似css中的before伪元素
node.removeChild(child)
从DOM中删除一个子节点,返回删除的节点
node.cloneNode()
node.cloneNode()方法返回调用该方法的节点的一个副本,也称为克隆节点/拷贝节点
注意:()括号为空或者为false,那么为浅拷贝,只复制标签,不复制里面的内容,括号中为true,复制标签及里面的内容
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>简单版发表留言title>
<style type="text/css">
textarea {
resize: none;
height: 65px;
display:block;
margin: 70px auto;
font-size: 15px;
color: #B8B8B8;
border: 5px black solid;
background-color: #E1E1E1;
}
button {
width: 50px;
height: 50px;
position: relative;
top: -140px;
left: 1100px;
background-color: #99DEE0;
color: #ffffff;
}
.box{
width: 520px;
margin: 30px auto;
border: 3px black solid;
}
li{
width: 300px;
background-color: #4FD6DD;
margin-bottom: 5px;
}
style>
head>
<body>
<textarea rows="10" cols="70">请发表一条善意的言论textarea>
<button>发表button>
<div class="box">
<ul>
评论区:
ul>
div>
<script type="text/javascript">
var text = document.querySelector('textarea');
var button = document.querySelector('button');
var ul = document.querySelector('ul');
text.onfocus = function(){
if (this.value === '请发表一条善意的言论'){
this.value = '';
this.style.backgroundColor = '#fff';
}
}
text.onblur = function(){
if (this.value == ''){
this.value = '请发表一条善意的言论';
}
}
button.onclick = function(){
if(text.value !== ''){
var li = document.createElement('li');
li.innerText = text.value;
ul.insertBefore(li,ul.children[0]);
}
}
script>
body>
html>
案例分析
因为数据是动态的,我们需要js动态生成,这里我们模拟数据,自己定义好数据。数据我们采用对象形式存储
所有的数据都是放在tbody里面的行里面
因为行很多,我们需要循环创建多个行(对应多少人)
每个行里面又有很多单元格(对应里面的数据),我们还继续使用循环创建多个单元格
最后一列单元格式删除,需要单独创建单元格
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>title>
<style type="text/css">
thead tr{
background-color:#CAC8C8;
font-size:20px;
}
th{
width: 70px;
}
style>
head>
<body>
<table border="1">
<thead>
<tr>
<th>姓名th>
<th>班级th>
<th>成绩th>
<th>操作th>
tr>
thead>
<tbody>
tbody>
table>
<script type="text/javascript">
// 1.创建数据
var datas = [{
name : '小明',
class : 1,
score : 98
}, {
name : '小红',
class : 2,
score : 88
}, {
name : '小刚',
class : 3,
score : 100
}];
// 2.往tbody中创建行,有几个人创建几行(由数组的长度决定)
var tbody = document.querySelector('tbody');
for (let i = 0; i < datas.length; i++) {
let tr = document.createElement('tr');
tbody.appendChild(tr);
// 3.创建单元格,单元格的数量取决于每个对象中属性个数
for (let j in datas[i]) {
//获取到的是对象的键,而不是值
let td = document.createElement('td');
td.innerText = datas[i][j];
tr.appendChild(td);
}
let td = document.createElement('td');
td.innerHTML = '删除';
tr.appendChild(td);
}
// 4.删除操作
var all_remove = document.querySelectorAll('a');
for (let i = 0; i < all_remove.length; i++) {
all_remove[i].onclick = function() {
tbody.removeChild(this.parentNode.parentNode);
}
}
script>
body>
html>