Web APIs
Web APIs 阶段
Web APIs 是 w3c组织的标准
Web APIs 我们主要学习 DOM和BOM
Web APIs 使我们JS所独有的部分
我们主要学习页面交互功能
需要使用JS基础的课程内容做基础
API
API是一些预定义的函数,目的是提供程序与开发人员基于软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
简单理解:
API就是给程序员提供的一种工具,以便能更轻松的实现想要完成的功能。
Web API
Web API 是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)
现阶段我们主要针对于浏览器讲解常用的API,主要针对浏览器做交互效果
DOM简介
简介
文档对象模型 (document object model) 是W3C组织推荐的处理可扩张标记语言(HTML或者XML)的标准编程接口
W3C已经定义了一系列DOM接口,通过这些接口可以改变网页中的内容、结构和样式。
DOM 树
文档:一个页面就是一个文档,DOM中使用document表示
元素:页面中所有的标签都是元素,DOM中使用element表示
节点:页面中所有内容都是节点(标签、属性、文本、注释) DOM中使用node表示
获取元素
根据ID获取
使用getElementByld()方法可以获取带有ID的元素对象
Document
的方法 getElementById()
返回一个匹配特定 ID的元素。由于元素的ID在大部分情况下要求是独一无二的,这个方法自然而然地成为了一个高效查找特定元素的方法。
<body>
<div id="time">2021-4-17</div>
<script>
//1.因为我们文档页面从上往下加载,所有得先有标签 所以我们script写在标签的下面
//2.get 获得 element 元素 by 通过 id
//3.参数 id是大小写敏感的字符串
var timer = document.getElementById('time');
console.log(timer);
//4.返回的是一个元素对象
console.log(typeof timer);
//5.console.dir 打印我们返回的元素对象 更好的查看里面的属性和方法
console.dir(timer)
</script>
</body>
根据标签名获取
Document.getElementsByTagName()
返回一个包括所有给定标签名称的元素的HTML集合HTMLCollection
。 整个文件结构都会被搜索,包括根节点。返回的 HTML集合
是动态的, 意味着它可以自动更新自己来保持和 DOM 树的同步而不用再次调用 document.getElementsByTagName()
。
还可以获取某个元素(父元素)内部所有指定标签名的子元素
注意:父元素必须是单个对象(必须指明是哪一对象元素),获取的时候不包括父元素自己
<body>
<ul>
<li>Hello World</li>
<li>Hello World</li>
<li>Hello World</li>
<li>Hello World</li>
<li>Hello World</li>
</ul>
<ol id="ol">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ol>
<script>
//1.返回的是 获取过来元素对象的集合 以伪数组的形式存在
var lis=document.getElementsByTagName('li');
console.log(lis);
//2.我们想要依次3打印里面的元素对象 我们可以采取 遍历的方式
for(var i=0;i<lis.length;i++){
console.log(lis[i]);
}
//3.如果页面只有一个元素 返回的还是伪数组
//4.如果页面中没有这个元素 返回的是空的伪数组的形式
//5.element.getElementsByTagName('标签名')
var ol = document.getElementById('ol');
console.log(ol.getElementsByTagName('li'));
</script>
通过HTML5 新增的方法获取
Document.getElementsByClassName()
返回一个包含了所有指定类名的子元素的类数组对象。当在document对象上调用时,会搜索整个DOM文档,包含根节点。你也可以在任意元素上调用getElementsByClassName()
方法,它将返回的是以当前元素为根节点,所有指定类名的子元素。
<body>
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="nav">
<ul>
<li>产品</li>
<li>首页</li>
</ul>
</div>
<script>
//1.getElementsByClassName 返回的是元素集合
var box = document.getElementsByClassName('box');
console.log(box);
//2. querySelector 返回指定选择器的第一个元素对象 切记里面的选择器 需要加符号 类加. id加#
var firstbox = document.querySelector('.box')
console.log(firstbox);
var nav = document.querySelector('#nav');
console.log(nav);
var li =document.querySelector('li');
console.log(li);
//3.querySelectorAll() 返回指定选择器的所有元素对象的集合
var allbox = document.querySelectorAll('.box');
console.log(allbox);
</script>
获取body和html元素
<body>
<script>
//1.获取body 元素
var bodyEle = document.body;
console.log(bodyEle);
console.dir(bodyEle);
//2.获取html 元素
var htmlEle = document.documentElement;
console.log(htmlEle);
</script>
</body>
事件基础
<body>
<button id="btn">Lucas</button>
<script>
//点击一个按钮 弹出对话框
//1.事件是有三部分组成 事件源 事件类型 事件处理程序 我们也称为 事件三要素
//(1) 事件源 事件被触发的对象 谁? 按钮
var btn = document.getElementById('btn');
//(2)事件类型 如何触发? 比如鼠标点击(onclick) 鼠标经过 键盘按下
//(3)事件处理程序 通过一个函数赋值的方式 完成
btn.onclick = function(){
alert('LYK');
}
</script>
修改元素的内容
<body>
<button>显示当前系统的时间</button>
<div>某个时间</div>
<p></p>
<script>
//当我们点击了按钮,div里面的文字会发生变化
//1.获取元素
var btn = document.querySelector('button');
var div = document.querySelector('div');
//2.注册事件
btn.onclick = function(){
div.innerHTML= getDate();
}
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>
innerText和innerHTML的区别
<body>
<div></div>
<p>
hello world
<span>123</span>
</p>
<script>
//innerText和 innerHTML区别
//1.innerText 不识别html标签 非标准
var div = document.querySelector('div');
//div.innerText = '<strong>今天是:</strong>2021';
//2.innerHTML 认识html标签
div.innerHTML = '<strong>今天是:</strong>2021';
//这两个属性是可读写的 可以获取里面的元素内容
var p = document.querySelector('p')
console.log(p.innerText);
console.log(p.innerHTML);
</script>
</body>
操作元素之修改元素的属性
<body>
<button id="Lucas">Lucas</button>
<button id="LYK">LYK</button> <br>
<img src="imag/南湖.jpg" title="Lucas" width="200px" height="200px">
<script>
//获取事件源
var Lucas = document.getElementById('Lucas');
var LYK = document.getElementById('LYK');
var img = document.querySelector('img');
//修改
LYK.onclick = function (){
img.src= 'imag/深圳.jpg';
img.title = 'LYK';
}
Lucas.onclick = function(){
img.src= 'imag/南湖.jpg';
img.title = 'Lucas';
}
</script>
</body>
案例:分时间问候并显示图片
<style>
img {
width: 300px;
}
</style>
</head>
<body>
<img src="imag/南湖.jpg" alt="">
<div>上午好</div>
<script>
var img = document.querySelector('img');
var div = document.querySelector('div');
//根据系统 不同时间来判断 所以需要用到日期内置时间
//利用多分支语句来设置 不同的图片
//需要一个图片 并且根据时间修改图片 就需要用到操作元素src属性
//需要一个div元素 显示不同的问候语 修改元素内容即可
//得到当前的小时数
var date = new Date();
var h = date.getHours();
//3.判断小时数 改变图片和文字信息
if(h<12){
img.src='imag/南湖.jpg';
div.innerHTML = 'good Morning';
}else if (h<18){
img.src='imag/深圳.jpg';
div.innerHTML = 'good afternoon';
}else {
img.src='imag/下姜.jpg';
div.innerHTML = 'good evening';
}
</script>
修改属性之表单的属性设置
<body>
<button>按钮</button>
<input type="text" value="输入内容">
<script>
//1.获取元素
var btn = document.querySelector('button');
var input = ducument.querySelector('input');
//2.注册事件 处理程序
btn.onclick = function() {
input.value = '被点击了';
}
</script>
</body>
案例:仿京东显示隐藏密码
<style>
.box {
width: 400px;
position: relative;
border-bottom: 1px solid #ccc;
margin: 100px auto;
}
.box input {
width: 370px;
height: 30px;
border: 0;
outline: none;
}
.box img {
width: 18px;
position: absolute;
right: 2px;
top: 2px;
}
</style>
</head>
<body>
<div class="box">
<label for=""></label>
<input type="password" id="password">
<img src="imag/biyan.png" alt="" id="eye">
</div>
<script>
//1.获取元素
var eye = document.getElementById('eye');
var password = document.getElementById('password') ;
//2.注册事件 处理程序
var flag=0;
eye.onclick = function() {
if(flag==0){
password.type = 'text'
flag=1;
}else {
password.type='password'
flag=0;
}
}
</script>
操作元素之修改样式属性
<style>
div {
width: 200px;
height: 200px;
background-color: brown;
}
</style>
</head>
<body>
<div></div>
<script>
var div = document.querySelector('div')
div.onclick = function(){
this.style.backgroundColor = 'purple';
}
</script>
</body>
案例:循环精灵图
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 250px;
margin: 100px auto;
}
.box li {
float: left;
width: 24px;
height: 24px;
background-color: crimson;
margin: 15px;
background: url("imag/精灵图.png") no-repeat;
text-decoration: none;
list-style: none;
}
</style>
</head>
<body>
<div class="box">
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<script>
var lis = document.querySelectorAll('li');
for(var i=0;i<lis.length;i++){
//让索引号*44
var index=i*44;
lis[i].style.backgroundPosition='0 -'+index+'px';
}
</script>
</body>
显示隐藏文本框
<style>
input {
color: #999999;
}
</style>
</head>
<body>
<input type="text" value="手机">
<script>
//1.获取事件
var input=document.querySelector('input');
//注册事件 获得焦点事件
input.onfocus = function(){
if(this.value==='手机'){
this.value = '';
}
//获得焦点需要把文本框的文字变黑
this.style.color='#333333';
}
input.onblur = function() {
if(this.value===''){
this.value='手机';
}
//失去焦点需要把文本框的文字变回原样
this.style.color='#999999';
}
</script>
使用className修改元素样式
<style>
div {
width: 250px;
height: 250px;
}
.change {
background-color: purple;
font-size: 20px;
margin-top: 100px;
line-height: 250px;
}
</style>
</head>
<body>
<div class="first">文本</div>
<script>
//1.使用element.style 获得修改元素样式 如果样式比较少 或者 功能简单的情况下使用
var test = document.querySelector('div')
test.onclick = function(){
//让我们当前类名变为.change
//2.我们可以通过 修改元素的className更改元素样式 适合于样式比较多或者功能复杂的情况
this.className='change';
//3.如果想要保留原先的类名 我们可以做多类名选择器
this.className='firsr change'
}
</script>
</body>
仿新浪注册页面
<style>
.register {
width: 600px;
margin: 100px auto;
}
.message {
display: inline-block;
font-size: 12px;
color: #999999;
background: url("imag/新浪.png") no-repeat 15px 15px left center;
padding-left: 20px;
}
.wrong {
color: crimson;
}
.rigth {
color: green;
}
</style>
</head>
<body>
<div class="register">
<input type="password" class="ipt">
<p class="message">请输入6-16位的密码</p>
</div>
<script>
//1.获取元素
var ipt = document.querySelector('.ipt');
var message = document.querySelector('.message');
//2.注册事件
ipt.onblur = function(){
//根据表单里面的长度 ipt.value.length
if(this.value.length<6 || this.value.length>16){
message.className='message wrong';
message.innerHTML = '您输入的位数不对要求6-16位';
}else {
message.className='message rigth';
message.innerHTML = '您输入的正确';
}
}
</script>
案例:开关灯
<style>
body {
background-color: black;
}
</style>
</head>
<body>
<button>按钮</button>
<script>
var btn = document.querySelector('button');
var body = document.querySelector('body')
var flag=0;
btn.onclick = function() {
if(flag==0){
body.style.backgroundColor='black';
flag=1;
}else {
body.style.backgroundColor='white';
flag=0;
}
}
</script>
操作元素
排他算法
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
//1.获取所有按钮元素
var btn = document.getElementsByTagName('button');
//2.btn得到是伪数组 里面的每一个元素 btn[i]
for(var i=0;i<btn.length;i++){
//先将所有按钮颜色都置为空
btn[i].onclick=function(){
for(var j=0;j<btn.length;j++){
btn[j].style.backgroundColor='';
}
this.style.backgroundColor='green';
}
}
</script>
</body>
案例:百度换肤效果
<style>
* {
margin: 0;
padding: 0;
}
body {
background: url("../imag/下姜.jpg") no-repeat center top;
background-size: 800px 800px;
}
li {
list-style: none;
}
.baidu {
overflow: hidden;
margin: 100px auto;
background: #ffffff;
width: 410px;
padding-top: 3px;
}
.baidu img {
width: 100px;
height: 100px;
}
</style>
</head>
<body>
<ul class="baidu">
<li><img src="../imag/下姜.jpg" alt=""></li>
<li><img src="../imag/南湖.jpg" alt=""></li>
<li><img src="../imag/深圳.jpg" alt=""></li>
</ul>
<script>
//获取元素
var imgs = document.querySelector('.baidu').querySelectorAll('img');
//循环注册事件
for(var i=0;i<imgs.length;i++){
imgs[i].onclick = function(){
document.body.style.backgroundImage='url('+this.src+')';
}
}
</script>
表格隔行变色
<style>
thead tr{
background-color: blue;
}
tr td{
text-align: center;
}
.bg {
background-color: tomato;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>代码</th>
<th>名称</th>
<th>最新公布净值</th>
<th>累计净值</th>
<th>前单位净值</th>
<th>净值增长率</th>
</tr>
</thead>
<tbody>
<tr>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
</tr>
<tr>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
</tr>
<tr>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
</tr>
<tr>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
</tr>
<tr>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
<td>0032525</td>
</tr>
</tbody>
</table>
<script>
var trs = document.querySelector('tbody').querySelectorAll('tr');
for(var i=0;i<trs.length;i++){
//鼠标经过事件
trs[i].onmouseover = function(){
this.className='bg';
}
//鼠标离开
trs[i].onmouseout = function(){
this.className = '';
}
}
</script>
表单的全选和反选
<style>
* {
margin: 0;
padding: 0;
}
thead {
background-color: blue;
}
table {
text-align: center;
}
</style>
</head>
<body>
<div class="wrap">
<table>
<thead>
<tr>
<th>
<input type="checkbox" id='All'>
</th>
<th>商品</th>
<th>价格</th>
</tr>
</thead>
<tbody id="tb">
<tr>
<td>
<input type="checkbox">
</td>
<td>iPhone8</td>
<td>8000</td>
</tr>
<tr>
<td>
<input type="checkbox">
</td>
<td>iPhone7</td>
<td>7000</td>
</tr>
<tr>
<td>
<input type="checkbox">
</td>
<td>iPhone6</td>
<td>6000</td>
</tr>
</tbody>
</table>
</div>
<script>
var all = document.getElementById('All');//全选按钮
var j_tbs = document.getElementById('tb').getElementsByTagName('input');//下面的复选按钮
//1.全选和取消全选 :让所有的复选框都跟随 全选
all.onclick = function(){
for(var i = 0; i<j_tbs.length;i++){
j_tbs[i].checked=this.checked;
}
}
//2.下面的小按钮状态发生了变化 上面的大按钮 也可能发生变化
for(var j= 0;j<j_tbs.length;j++){
j_tbs[j].onclick=function(){
var flag=true;
for(var z=0;z<j_tbs.length;z++){
if(!j_tbs[z].checked){
flag=flase;
break;//退出for循环 提高执行效率
}
}
all.checked=flag;
}
}
</script>
</body>
自定义属性的操作
<body>
<div id="demo" index="1"></div>
<script>
var div = document.getElementById('demo');
//1.获取元素的属性值
//(1)element.属性
console.log(div.id);
//(2)element.getAttribute('属性') 我们程序员自定义的属性 成为自定义属性
console.log(div.getAttribute('id'));
console.log(div.getAttribute('index'));
</script>
</body>
区别:
- element.属性 获取内置属性值(元素本身自带的属性)
- element.getAttribute(’属性‘):主要获取自定义的属性 我们程序员程序员自定义的属性
设置属性值
element.属性=’值‘ 设置内置属性值
element.setAttribute(‘属性’,‘值’) 设置自定义的属性值
<body>
<div id="demo" index="1" class="nav"></div>
<script>
var div = document.getElementById('demo');
//1.获取元素的属性值
//(1)element.属性
console.log(div.id);
//(2)element.getAttribute('属性') 我们程序员自定义的属性 成为自定义属性
console.log(div.getAttribute('id'));
console.log(div.getAttribute('index'));
//2.设置元素属性值
//(1)element.属性 = '值'
div.id='test';
div.className = 'navs'
//(2)element.setAttribute('属性','值') 设置自定义的属性值
div.setAttribute('index','2');
div.setAttribute('class','navss');
//3.移除属性
div.removeAttribute('index');
</script>
</body>
案例:tab栏切换
<style>
.tab_list {
width: 700px;
margin: 200 auot;
overflow: hidden;
}
.tab_con {
padding-left: 39px;
}
.tab_list li {
float: left;
height: 39px;
list-style: none;
line-height: 39px;
text-align: center;
cursor: pointer;
width: 100px;
background-color: teal;
}
.tab_list .current {
background-color: #c81623;
color: white;
}
.item {
display: none;
}
</style>
</head>
<body>
<div class="tab">
<div class="tab_list">
<ul>
<li class="current">商品介绍</li>
<li>规格与包装</li>
<li>售后保障</li>
<li>商品评价</li>
<li>手机社区</li>
</ul>
</div>
<div class="tab_con">
<div class="item" style="display: block;">
商品介绍模块内容
</div>
<div class="item">
规格与包装模块内容
</div>
<div class="item">
售后保障模块内容
</div>
<div class="item">
商品评价模块内容
</div>
<div class="item">
手机社区模块内容
</div>
</div>
</div>
<script>
//获取元素
var tab_list = document.querySelector('.tab_list');
var lis = tab_list.querySelectorAll('li');
var items = document.querySelectorAll('.item');
//for循环绑定点击事件
for(var i = 0; i<lis.length;i++){
//开始给5个小li 设置索引号
lis[i].setAttribute('index',i);
//1.上面的模块卡 点击某一个 当前这一个底色会是红色 其余不变(排他思想) 修改类名的方式
lis[i].onclick = function(){
//现将所有li的样式消失
for(var i =0 ;i<lis.length;i++){
lis[i].className = '';
}
//留下自己
this.className = 'current';
//2.下面的显示内容模块
var index= this.getAttribute('index');
//干掉所有人 让其余的item 这些div消失 隐藏
for(var i = 0;i<items.length;i++){
items[i].style.display='none';
}
//留下自己
items[index].style.display='block';
}
}
</script>
</body>
H5自定义属性
自定义属性的目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
自定义属性是通过获取属性getAttribute(‘属性’)
但有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性
H5给我们新增了自定义属性:
-
H5规定自定义属性data-开头作为属性名并且赋值
比如
-
H5新增element.dataset.index 或者element.dataset[‘index’] 获取自定义属性的方法
dataset是一个集合里面存放了所有自定义属性的集合
<body>
<div data-index="2" data-list-name="Lucas"></div>
<script>
var div = document.querySelector('div');
div.setAttribute('data-time','20');
console.log(div.getAttribute('data-index'));
console.log(div.getAttribute('data-list-name'));
console.log(div.dataset);
console.log(div.dataset.index);
//如果自定义属性里面有多个-链接的单词 我们获取的时候采取 驼峰命名法
console.log(div.dataset.listName);
</script>
</body>
节点
一般的,节点至少拥有nodeType(节点类型)、nodeName(节点名称)、和nodeValue(节点值)这三个基本属性
元素节点 nodeType 为 1
属性节点 nodeType 为 2
文本节点 nodeType 为 3 (文本节点包括文字、空格、换行)
<body>
<!--节点的优点-->
<div>我是div</div>
<span>我是span</span>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<div class="box">
<span class="erweima">x</span>
</div>
<script>
//1.父节点 parentNode
var erweima = document.querySelector('.erweima');
var box = document.querySelector('.box');
var ul = document.querySelector('ul');
//得到是里元素最近的父亲 如果找不到父节点 就返回空
erweima.parentNode;
console.log(box.nodeType);
//2.子节点 childNodes 所有的子节点 包含 元素节点 本文节点等等 比较麻烦 不建议使用
//children 是一个读属性 返回所有子元素节点 它制单会子元素节点 其余节点不返回!
console.log(ul.children);
</script>
节点操作之第一个子元素和最后一个子元素
firstElementchild 返回的是第一子元素节点 找不到返回null
lastElementchild 返回的是最后一个子元素节点 找不到返回null
在实际开发中的写法 既没有兼容性的问题 又返回第一个元素
parentNode.children[0] 第一子元素节点
parentNode.children[parentNode.children.length-1] 最后一个子元素节点
案例:新浪下拉菜单
<style>
*{
margin:0;
padding:0;
}
a {
text-decoration: none;
}
li {
list-style: none;
}
div {
width: 400px;
margin-top: 100px auto;
}
div ul li {
float: left;
width: 100px;
height: 30px;
line-height: 30px;
text-align: center;
}
div a {
display: block;
width: 100px;
height: 30px;
background:#ccc;
}
.nav ul {
display: none;
}
.nav>li>a:hover {
background-color: #eee;
}
</style>
</head>
<body>
<div>
<ul class="nav">
<li>
<a href="#">微博</a>
<ul>
<li><a href="#">私信</a> </li>
<li><a href="#">私信</a> </li>
<li><a href="#">私信</a> </li>
</ul>
</li>
<li>
<a href="#">博客</a>
<ul>
<li><a href="#">私信</a> </li>
<li><a href="#">私信</a> </li>
<li><a href="#">私信</a> </li>
</ul>
</li>
<li>
<a href="#">邮箱</a>
<ul>
<li><a href="#">私信</a> </li>
<li><a href="#">私信</a> </li>
<li><a href="#">私信</a> </li>
</ul>
</li>
</ul>
</div>
<script>
//1.获取元素
var nav = document.querySelector('.nav');
var lis = nav.children;
for(var i = 0;i<lis.length;i++){
lis[i].onmouseover = function(){
this.children[1].style.display = 'block';
}
lis[i].onmouseout = function(){
this.children[1].style.display = 'none';
}
}
</script>
</body>
兄弟节点
1.node.nextSibling
下一个兄弟结点 包含元素结点 或者文本节点
2.node.preSibling
上一个兄弟节点 包含元素结点 或者文本节点
3.node.nextElementSibiling
得到下一个兄弟元素节点
4.node.preElementSibling
得到上一个兄弟元素节点
创建节点
document.createElement(‘tagName’)
添加节点
node.appendChild(child)
案例:简单版发布留言
<style>
textarea {
width: 30%;
margin-left: 40px;
margin-top: 50px;
}
li {
background-color: pink;
font-size: 14px;
list-style: none;
width: 40%;
margin-top: 20px;
}
</style>
</head>
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发布</button>
<ul>
</ul>
<script>
//1.获取元素
var text = document.querySelector('textarea');
var btn = document.querySelector('button');
var ul = document.querySelector('ul');
//2.注册事件
btn.onclick = function(){
//先判断文本域的内容是否为空
if(text.value == 0 ){
alert('请先输入文字!');
}
else {
//1.创建节点
var li = document.createElement('li');
//给节点赋值
li.innerHTML = text.value;
//添加节点
//添加到最新一个的后面
//ul.appendChild(li);
//添加到最新一个的前面
ul.insertBefore(li,ul.children[0]);
}
}
</script>
删除节点
node.removeChild(child)
<body>
<button>删除</button>
<ul>
<li>张三</li>
<li>李四</li>
<li>王五</li>
</ul>
<script>
//获取元素
var btn = document.querySelector('button');
var ul = document.querySelector('ul');
//注册事件
btn.onclick = function(){
if(ul.children.length==0){
this.disabled=true;
}else {
ul.removeChild(ul.children[0]);
}
}
</script>
案例:删除留言操作
阻止链接跳转 需要添加javascript:void(0)或者javascript:;
<style>
textarea {
width: 30%;
margin-left: 40px;
margin-top: 50px;
}
li {
background-color: pink;
font-size: 14px;
list-style: none;
width: 40%;
margin-top: 20px;
}
li a {
float: right;
}
</style>
</head>
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发布</button>
<ul>
</ul>
<script>
//1.获取元素
var text = document.querySelector('textarea');
var btn = document.querySelector('button');
var ul = document.querySelector('ul');
//2.注册事件
btn.onclick = function(){
//先判断文本域的内容是否为空
if(text.value == 0 ){
alert('请先输入文字!');
}
else {
//1.创建节点
var li = document.createElement('li');
//给节点赋值
li.innerHTML = text.value+"<a href='javascript:;'>删除</a>";
//添加节点
//添加到最新一个的后面
//ul.appendChild(li);
//添加到最新一个的前面
ul.insertBefore(li,ul.children[0]);
//删除元素 当前元素的父亲
var as = document.querySelectorAll('a');
for(var i = 0;i<as.length;i++){
as[i].onclick = function() {
ul.removeChild(this.parentNode);
}
}
}
}
</script>
复制节点
node.cloneNode();
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul = document.querySelector('ul');
//1.node.cloneNode();括号里面为空或者是false 为浅拷贝 只复制标签不复制内容
var lili = ul.children[0].cloneNode(true);//为true 深度拷贝 内容也拿过来
ul.insertBefore(lili,ul.children[2]);
</script>
</body>
案例:动态创建单元格
<style>
* {
margin: 0 auto;
padding: 0;
}
table {
margin-top: 200px;
width: 400px;
height: 400px;
}
th {
height: 40px;
background-color: blue;
border: 1px solid red;
line-height: 20px;
text-align: center;
}
td {
height: 40px;
border: 1px solid red;
line-height: 20px;
text-align: center;
}
</style>
</head>
<body>
<table cellspacing="0">
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
//1.先准备好学生的数据
var datas =[
{
name:'张三',
subject:'JavaScript',
score: 100
},{
name:'李四',
subject:'JavaScript',
score: 95
},{
name:'王五',
subject:'JavaScript',
score: 90
}
];
//2.往tbody中创建行
var tbody = document.querySelector('tbody');
for(var i = 0;i<datas.length;i++){
var tr = document.createElement('tr');
tbody.appendChild(tr);
//行里面创建单元格 单元格的数量取决于每个对象里面的属性数量
for(var k in datas[i]){
//创建单元格
var td = document.createElement('td');
//把对象里面的属性值 添加进去
td.innerHTML = datas[i][k];
tr.appendChild(td);
}
//创建有删除两个字的单元格
var td = document.createElement('td');
td.innerHTML = "<a href='javascript:;'>删除</a>";
tr.appendChild(td);
}
//删除单元格
var as = document.querySelectorAll('a');
for(var i = 0 ;i<as.length;i++){
as[i].onclick = function(){
//点击a 删除 行 node.removeChild(child)
tbody.removeChild(this.parentNode.parentNode);
}
}
</script>
</body>
创建元素
document.write 创建元素 是直接将内容写入页面的内容流, 但是文档流执行完毕,则它会导致页面全部重绘
innerHTML 创建元素 但如果采取数组形式拼接,这个效率最高
documen.createElement 创建元素 远远高于上面的方法
DOM操作重点核心
1.创建
document.write()
innerHTML
document.creatELement
2.增
node.appenChild(child)
node.insertbefore(要插入的节点,插在那个节点前面)
3.删除
node.removeChild()
4.改
修改元素的属性: src,href,title等
修改普通元素的内容:innerHTML innerText
修改表单元素:value,type,disable
修改元素样式:style className
4.查
querySelector querySelectorAll
利用节点操作获取元素 :parentNode (父) children(子) 兄(previousElementSibling、nextELementSibling)
5.属性操作
setAttribute :设置dom属性
getAttribute:得到dom属性
removeAttribute:删除dom属性
注册事件
给元素添加事件 ,称为注册事件 或者 绑定事件
注册事件有两种方式 传统方式和方法监听注册方式
传统注册方式:
- 利用on开头的onclick
- 特点:注册事件的唯一性
- 同一元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
方法监听注册方式
- w3c 标准推荐方式
- eventTarget.addEventListener(type,listener)它是一个方法
type:事件类型字符串,比如click、mouseover 注意这里不要带on
listener: 事件处理函数 事件发生时 会调用该监听函数
<body>
<button>传统注册事件</button>
<button>方法监听注册事件</button>
<script>
var btns = document.querySelectorAll('button');
//1.传统注册事件
btns[0].onclick = function(){
alert('hi');
}
btns[0].onclick = function(){
alert('How are you');
}
//2.方法监听注册事件
//同一个元素 同一个事件可以添加多个侦听器(事件处理程序)
btns[1].addEventListener('click',function(){
alert(22);
})
btns[1].addEventListener('click',function(){
alert(33);
})
</script>
删除事件
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<script>
var divs = document.querySelectorAll('div');
//传统 方式 删除事件
divs[0].onclick = function(){
alert(11);
divs[0].onclick = null;
}
//方法监听解绑事件
divs[1].addEventListener('click',fn)
function fn(){
alert(22);
divs[1].removeEventListener('click',fn);
}
</script>
</body>
DOM事件流
事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特点的顺序传播,这个传播过程既DOM事件流。
比如我们给一个div注册了点击事件:
DOM事件流分为三个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
事件冒泡:IE最早提出,事件开始时由最具体的元素接受,然后逐级向上传播到DOM最顶层节点的过程
事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接受的过程
注意:
我们在实际开发中 很少用事件捕获 我们更关注事件冒泡
有些事件是没有冒泡的 比如 onblur onfocus onmouseenter onmouseleave
<style>
* {
margin: 0 auto;
padding: 0;
}
.father {
margin-top: 100px;
position: relative;
width: 300px;
height: 300px;
background-color: blue;
}
.son {
position: absolute;
margin-top: 100px;
margin-left: 100px;
width: 100px;
height: 100px;
background-color: chartreuse;
line-height: 100px;
text-align: center;
}
</style>
</head>
<body>
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
//don事件流三个阶段
//1.JS代码中只能执行捕获或者冒泡其中一个阶段。
//2.onclick 只能得到冒泡阶段
//3.捕获阶段 如果addEventListener 第三个参数是 true 那么则处于捕获阶段
//document->html->body->father->son
// var son = document.querySelector('.son');
//var father = document.querySelector('.father');
// son.addEventListener('click',function(){
// alert('son');
// },true);
//father.addEventListener('click',function(){
// alert('father');
//},true);
//4.冒泡阶段 如果addEventListener 第三个参数是 false 那么则处于捕获阶段
//son->father->body->html->document
var son = document.querySelector('.son');
var father = document.querySelector('.father');
son.addEventListener('click',function(){
alert('son');
},false);
father.addEventListener('click',function(){
alert('father');
},false);
</script>
</body>
事件对象
事件对象常见的属性和方法
<body>
<div>123</div>
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
<script>
//事件对象
var div = document.querySelector('div');
//div.onclick = function(event){
// console.log(event);
//}
div.addEventListener('click',function(event){
console.log(event);
})
//1.event 就是一个事件对象 写到我们侦听函数的 小括号里面 当形参看
//2. 事件对象只有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
//3. 事件对象 是 我们事件的一系列相关的数据的集合 跟事件相关的 比如鼠标点击了里面包含了
//鼠标的相关信息、鼠标坐标啊 如果是键盘事件里面包含了键盘的事件相关信息 比如
//判断用户按下来那个按键
//4.这个事件对象 我们可以由自己命名 比如event e evt
//e.target 和 this 的区别
//e.target返回的是触发事件的对象(元素) this 返回的是绑定事件的对象(元素)
var ul = document.querySelector('ul');
ul.addEventListener('click',function(e){
//谁触发事件 就指向谁
console.log(e.target);
console.log(this);
})
</script>
<body>
<div>123</div>
<a href="http://www.baidu.com">百度</a>
<form action="http://www.baidu.com">
<input type="submit" value="提交" name="sub">
</form>
<script>
//常见事件对象的属性和方法
//1.返回事件类型
var div =document.querySelector('div')
div.addEventListener('click',fn)
function fn(e){
console.log(e.type);
}
//2.阻止默认行为(事件)让链接不跳转 提交按钮不提交
var a = document.querySelector('a');
var input = document.querySelector('input');
a.addEventListener('click',function(e){
e.preventDefault();
});
input.addEventListener('click',function(e){
e.preventDefault();
});
//3.传统注册方式
a.onclick = function(e) {
//普通浏览器
e.preventDefault();
//低版本浏览器
e.returnValue;
//return false 也可以阻止默认行为 没有兼容性的问题 但是return 后面的语句就不在执行了
}
</script>
</body>
阻止事件冒泡
var son = document.querySelector('.son');
var father = document.querySelector('.father');
son.addEventListener('click',function(e){
alert('son');
e.stopPropagation();//阻止冒泡
},false);
father.addEventListener('click',function(e){
alert('father');
},false);
</script>
事件委托
事件委托又称事件代理,在jQuery里面称为事件委派
事件委托的原理:
不是每一个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每一个子节点
以上案例:给ul注册点击事件,然后利用事件对象的target来找到当前点击的li,因为点击li,事情会冒泡到ul上,ul有注册事件,就会出大事件监听器。
<body>
<ul>
<li>111111111111111111111</li>
<li>111111111111111111111</li>
<li>111111111111111111111</li>
<li>111111111111111111111</li>
<li>111111111111111111111</li>
<li>111111111111111111111</li>
</ul>
<script>
//事件委托的核心原理:给父节点添加侦听器,利用事件冒泡影响每一个子节点
var ul = document.querySelector('ul');
var lis = ul.querySelectorAll('li');
ul.addEventListener('click',function(e){
//alert('111111111111111111111');
//e.target 这个得到我们点击的对象
for(var i = 0;i<lis.length;i++){
lis[i].style.backgroundColor='';
}
e.target.style.backgroundColor='pink';
})
</script>
禁止选中文字和右键菜单
<body>
我是一段不愿意分享的文字
<script>
//1.contextmenu 我们可以禁用右键菜单
document.addEventListener('contextmenu',function(e){
e.preventDefault();
})
//2.禁止选中文字 selectstart
document.addEventListener('selectstart',function(e){
e.preventDefault();
})
</script>
</body>
获得鼠标在页面中的坐标
<style>
body {
height: 3000px;
}
</style>
</head>
<body>
<script>
//鼠标事件对象 MouseEvent
document.addEventListener('click',function(e){
//1.client 鼠标在可视区x,y的距离
console.log(e.clientX);
console.log(e.clientY);
console.log("=====================");
//2.page 鼠标在页面文本的x和y的坐标
console.log(e.pageX);
console.log(e.pageY);
//3.screen 鼠标在电脑屏幕的x和y坐标
console.log(e.screenX);
console.log(e.screenY);
})
</script>
</body>
案例:跟随鼠标的图片
<style>
img{
position: absolute;
}
</style>
</head>
<body>
<img src="../imag/biyan.png" alt="">
<script>
var pic = document.querySelector('img');
document.addEventListener('mousemove',function(e){
//1.mousemove 只要我们鼠标移动 1px 就会触发这个事件
//2.核心原理:每次鼠标移动 我们都会获得最新的鼠标坐标 把这个x和y给图片的top和left
var x= e.pageX;
var y=e.pageY;
//3.千万不要忘记 加上px
pic.style.top=y+'px';
pic.style.left=x+'px';
})
</script>
</body>