到了我最为感兴趣的部分了,要戒骄戒躁,毕竟还没出发多远,不能想着一步登天,稳扎稳打
从这节视频到那节视频结束
JS基础阶段
Web APIs阶段
JS基础 学习的是ECMAScript基础语法,这为后面作铺垫
Web APIs是JS应用,大量使用JS基础语法做交互效果
API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码或理解内部工作机制的细节
简单理解:API是程序员提供的一种工具,以便能够轻松的实现想要完成的功能
Web API是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)
现阶段主要针对于浏览器讲解常用的API,对浏览器做交互效果
如:想要浏览器弹出一个警示框,直接使用alert(‘弹出’)
MDN详细 API:https://developer.mozilla.org/zh-CN/docs/Web/API
因为Web API很多,所以称 这个阶段为Web APIs
API是程序员提供的一个接口,帮助实现某种功能,会使用就好,不必纠结内部实现机制
Web API主要针对浏览器提供的接口,主要针对浏览器做交互效果
Web API一般有输入和输出(函数的传参和返回值),Web API很多都是方法(函数)
学习Web API可以结合前面学习内置对象方法的思路来学习
文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口
W3C 已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式
文档包含节点,节点包含元素
DOM在实际开发中主要用来操作元素
获取页面中的元素可以使用以下几种方式:
使用getElementById()
方法可以获取带有ID的元素对象
使用getElementsByTagName()方法可以返回带有指定标签名的对象集合
还可以获取某个元素(父元素)内部所有指定标签名的子元素
element.getElementsByTagName('标签名');
注意:父元素必须是单个对象(必须指明是哪一个元素对象),获取的适合不包括父元素本身
<!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>Document</title>
</head>
<body>
<ul>
<li>知否知否,应是等你好久1</li>
<li>知否知否,应是等你好久2</li>
<li>知否知否,应是等你好久3</li>
<li>知否知否,应是等你好久4</li>
</ul>
<ol id="ol">
<li>生僻字</li>
<li>生僻字</li>
<li>生僻字</li>
</ol>
<script>
var lis = document.getElementsByTagName('li');
console.log(lis);
console.log(lis[0]);
for (var i = 0; i < lis.length; i++) {
console.log(lis[i]);
}
// 如果页面中只有一个标签,返回的依旧是伪数组形式
var tes = document.getElementsByTagName('div');
console.log(tes); // 得到的是一个空的伪数组形式
// var ol = document.getElementsByTagName('ol'); //[ol]
// console.log(ol[0].getElementsByTageName('li'));
var ol = document.getElementById('ol');
console.log(ol.getElementsByTagName('li'));
</script>
</body>
</html>
document.getElementsByClassName('类名'); // 根据类名返回元素对象集合
document.querySelector('选择器'); // 根据指定选择器返回第一个元素对象
document.querySelectorAll('选择器'); // 根据指定选择器返回
<!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>Document</title>
</head>
<body>
<div class="box">盒子</div>
<div class="box">盒子</div>
<div id="nav">
<ul>
<li>首页</li>
<li>产品</li>
</ul>
</div>
<script>
// getElementsByClassName 根据类名获得某些元素集合
var boxs = document.getElementsByClassName('box');
console.log(boxs);
// querySelector 返回指定选择器的第一个元素对象
var firstBox = document.querySelector('.box');
console.log(firstBox);
var nav = document.querySelector('#nav');
console.log(nav);
var li = document.querySelector('li');
console.log(li);
var allBox = document.querySelectorAll('.box');
console.log(allBox);
var lis = document.querySelectorAll('li');
console.log(lis);
</script>
</body>
</html>
获取body元素
document.body // 返回body元素对象
document.documentElement // 返回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>Document</title>
</head>
<body>
<script>
// 获取body 元素
var bodyEle = document.body;
console.log(bodyEle);
console.dir(bodyEle);
// 获取html 元素
var htmlEle = document.documentElement;
console.log(htmlEle);
</script>
</body>
</html>
JavaScript使我们有能力创建动态页面,而事件使可以被JavaScript侦测到的行为
简单理解:触发–响应机制
网页中每个元素都可以产生某些可以触发JavaScript的事件
在用户点击某按钮时产生一个事件,然后去执行某些操作
事件三要素:谁触发的,怎么触发的,触发的后果
<!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>Document</title>
</head>
<body>
<button id="btn">唐伯虎</button>
<script>
// 点击一个按钮,弹出对话框
// 事件是有三部分组成 事件源 事件类型 事件处理程序 也称为事件三要素
// 事件源 事件被触发的对象 按钮
var btn = document.getElementById('btn');
// 事件类型 如何触发 比如鼠标点击(onclick) 还是鼠标经过 还是键盘按下
// 事件处理程序 通过一个函数赋值的方式 完成
btn.onclick = function() {
alert('点秋香');
}
</script>
</body>
</html>
效果
执行事件的步骤
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
分析事件三要素
JavaScript的DOM操作可以改变网页内容、结构和样式,可以利用DOM操作元素来改变元素的内容、属性等
element.innerText
从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉
element.innerHTML
起始位置到终止位置的全部内容,包括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>Document</title>
<style>
div+p {
width: 300px;
height: 30px;
line-height: 30px;
color: #fff;
background-color: pink;
}
</style>
</head>
<body>
<button>显示当前系统时间</button>
<div>某个时间</div>
<p>123</p>
<script>
// 点击按钮,div 里面的文字会发生变化
// 获取元素
var btn = document.querySelector('button');
var div = document.querySelector('div');
// 注册事件
btn.onclick = function() {
// div.innerText = '2019-6-6';
div.innerText = 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>
</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>Document</title>
</head>
<body>
<div></div>
<p>
我是文字
<span>123</span>
</p>
<script>
// innerText不识别 html标签 去除空格和换行
var div = document.querySelector('div');
div.innerText = '今天是:/strong> 2023';
div.innerHTML = '今天是: 2023';
var p = document.querySelector('p');
console.log(p.innerText);
console.log(p.innerHTML);
</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>Document</title>
<style>
img {
width: 300px;
}
</style>
</head>
<body>
<button id="ldh">刘德华</button>
<button id="zxy">张学友</button><br/>
<img src="../img/ldh.jpg" alt="" title="刘德华">
<script>
// 修改元素属性
// 获取元素
var ldh = document.getElementById('ldh');
var zxy = document.getElementById('zxy');
var img = document.querySelector('img');
// 注册事件
zxy.onclick = function() {
img.src = '../img/zxy.jpg';
img.title = '张学友思密达';
}
ldh.onclick = function() {
img.src = '../img/ldh.jpg';
img.title = '刘德华'
}
</script>
</body>
</html>
效果如下
案例分析
- 根据系统不同时间来判断,所以需要用到日期内置对象
- 利用多分支语句来设置不同的图片
- 需要一个图片,并且根据时间修改图片,就需要用到操作元素src属性
- 需要一个div元素,显示不同问候语,修改元素内容即可
<!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>Document</title>
</head>
<body>
<img src="../img/swh.gif" alt="">
<div>上午好</div>
<script>
var img = document.querySelector('img');
var div = document.querySelector('div');
var date = new Date();
var h = date.getHours();
if (h < 12) {
img.src = '../img/swh.gif';
div.innerHTML = '亲,上午好,好好写代码';
} else if (h < 18) {
img.src = '../img/xwh.gif';
div.innerHTML = '亲,下午好,好好写代码';
} else {
img.src = '../img/wsh.gif';
div.innerHTML = '亲,晚上好,好好写代码';
}
</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>Document</title>
</head>
<body>
<button>按钮</button>
<input type="text" value="输入内容">
<script>
var btn = document.querySelector('button');
var input = document.querySelector('input');
btn.onclick = function() {
// 表单里面的值(文字内容) 通过value来修改
input.value = '被点击了';
// 如果想要某个表单被禁用 不能再点击 disabled 禁用按钮
// btn.disabled = true;
this.disabled = true;
// this 指向的事件函数的调用者
}
</script>
</body>
</html>
案例分析
- 核心思路:点击眼睛按钮,把密码框类型改为文本框就可以看见里面的密码
- 一个按钮两个状态,点击一次,切换为文本框,继续点击一次,切换为密码框
- 算法:利用一个flag变量,来判断flag的值,如果是1就切换为文本框,flag设置为0,如果是0就切换为密码框,flag设置为1
<!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>Document</title>
<style>
.box {
position: relative;
width: 400px;
border: 1px solid #ccc;
margin: 100px auto;
}
.box input {
width: 370px;
height: 30px;
border: 0;
outline: none;
}
.box img {
position: absolute;
top: 6px;
right: 6px;
width: 20px;
}
</style>
</head>
<body>
<div class="box">
<label for="">
<img src="../img/eye_off.png" alt="" id="eye">
</label>
<input type="password" name="" id="pwd">
</div>
<script>
// 获取元素
var eye = document.getElementById('eye');
var pwd = document.getElementById('pwd');
// 注册事件 处理程序
var flag = 0;
eye.onclick = function() {
if (flag == 0) {
pwd.type = 'text';
eye.src = '../img/eye_open.png';
flag = 1;
} else {
pwd.type = 'password';
eye.src = '../img/eye_off.png';
flag = 0;
}
}
</script>
</body>
</html>
可以通过JS修改元素的大小、颜色、位置等样式
element.style 行内样式操作
和 element.className 类名样式操作
注意:
如果直接对div元素使用元素选择器,会出现实际高度高于设定高度2倍
如下(导致原因不详,HTML 和 CSS知识忘了不少)
故而不直接对其进行元素选择,用类选择器
<!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>Document</title>
<style>
.circle {
width: 200px;
height: 200px;
background-color: pink;
border-radius: 50%;
}
</style>
</head>
<body>
<div class="circle"></div>
<script>
// 获取元素
var div = document.querySelector('div');
// 注册事件 处理程序
div.onclick = function() {
this.style.backgroundColor = 'purple';
this.style.width = '250px';
}
</script>
</body>
</html>
效果
案例分析
- 核心思路 利用样式的显示和隐藏完成,display:none隐藏元素,display:block显示元素
- 点击按钮,就让这个二维码盒子隐藏起来
<!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>Document</title>
<style>
.box {
position: relative;
width: 0px;
height: 0px;
border: 0px solid #ccc;
margin: 100px auto;
font-size: 12px;
text-align: center;
color: #f40;
}
.box img {
width: 60px;
margin-top: 5px;
}
.close-btn {
position: absolute;
top: 5px;
left: -16px;
width: 14px;
height: 14px;
border: 1px solid #ccc;
line-height: 14px;
font-family: Arial, Helvetica, sans-serif;
cursor: pointer;
}
</style>
</head>
<body>
<div class="box">
<img src="../img/tao.jpg" alt="">
<span class="close-btn">x</i>
</div>
<script>
// 获取元素
var btn = document.querySelector('.close-btn');
var box = document.querySelector('.box');
// 注册事件 程序处理
btn.onclick = function() {
box.style.display = 'none'
}
</script>
</body>
</html>
效果
- 精灵图图片排列有规律
- 核心思路:利用for循环 修改精灵图片的 背景位置background-position
<!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>Document</title>
<style>
* {
list-style: none;
margin: 0;
padding: 0;
}
.box {
width: 250px;
height: 180px;
margin: 100px auto;
}
.box li {
float: left;
width: 24px;
height: 24px;
background-color: pink;
margin: 10px 0 30px 30px;
background: url('../img/jlt.png') no-repeat;
}
</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 就是每个li 的背景y坐标 index就是y的坐标
var index = i * 44;
lis[i].style.backgroundPosition = '0 -' + index + 'px'
}
</script>
</body>
</html>
案例分析
- 首先表单需要2个新事件,获得焦点 onfocus 失去焦点onblur
- 如果获得焦点,判断表单里面内容是否为默认文字,如果是默认文字,就清空表单内容
- 如果失去焦点,判断表单内容是否为空,如果为空,则表单内容改为默认文字
<!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>Document</title>
<style>
input {
color: #999;
}
</style>
</head>
<body>
<input type="text" value="手机">
<script>
// 获取元素
var text = document.querySelector('input');
// 注册事件 获得焦点事件
text.onfocus = function() {
console.log('得到了焦点');
if (this.value === '手机') {
this.value = '';
}
// 获得焦点 需要把文本框内的文字颜色变黑
this.style.color = '#333';
}
// 注册事件 失去焦点事件
text.onblur = function() {
console.log('失去了焦点');
if (this.value === '') {
this.value = '手机';
}
// 失去焦点 需要把文本框内的文字颜色变浅
this.style.color = '#999';
}
</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>Document</title>
<style>
.circle {
width: 100px;
height: 100px;
background-color: pink;
}
.change {
background-color: purple;
color: #fff;
font-size: 25px;
height: 100px;
width: 100px;
margin-top: 100px;
}
</style>
</head>
<body>
<div class="circle">文本</div>
<script>
var test = document.querySelector('div');
test.onclick = function() {
// 让当前元素的类名改为 change
// this.className = 'change';
// 如果想保留原先的类名,可以这么做 多类名选择器
this.className = 'circle change';
}
</script>
</body>
</html>
效果
案例分析
- 首先判断的事件是表单失去焦点onblur
- 如果输入正确则提示正确的信息颜色为绿色小图标
- 如果输入不是6到16位,则提示错误信息颜色为红色小图标
- 因为里面变化样式较多,采取className修改样式
<!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>Document</title>
<style>
div {
width: 600px;
margin: 100px auto;
}
.icon {
width: 16px;
height: 16px;
margin:0 1px -3px 0;
display: inline-block;
}
.message {
display: inline-block;
font-size: 12px;
color: #999;
padding-left: -6px;
}
</style>
</head>
<body>
<div class="regiester">
<input type="password" class="ipt">
<img src="../img/mess.png" class="icon">
<p class="message">
请输入6~16位密码
</p>
</div>
<script>
var ipt = document.querySelector('.ipt');
var img = document.querySelector('.icon');
var message = document.querySelector('.message');
ipt.onblur = function() {
// 根据表单值的长度 ipt.value.length
if (this.value.length < 6 || this.value.length > 16) {
img.src = '../img/wrong.png';
message.innerHTML = '您输入的位数不对要求6~16位';
message.style.color = 'red';
} else {
img.src = '../img/right.png';
message.innerHTML = '您输入的正确';
message.style.color = '#000';
}
}
</script>
</body>
</html>
操作元素是DOM核心内容
效果
<!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>Document</title>
</head>
<body>
<button>关灯</button>
<script>
var btn = document.querySelector('button');
var bd = document.body;
var flag = false;
btn.onclick = function() {
flag = !flag;
if (flag) {
bd.style.backgroundColor = 'black';
this.innerHTML = '开灯';
} else {
bd.style.backgroundColor = 'white';
this.innerHTML = '关灯';
}
}
</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>Document</title>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
// 获取所有按钮元素
var btns = document.getElementsByTagName('button');
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
// 先把所有按钮的背景颜色去掉
for (var i = 0; i < btns.length; i++) {
btns[i].style.backgroundColor = '';
}
// 然后让当前按钮的背景颜色位pink
this.style.backgroundColor = 'pink';
}
}
</script>
</body>
</html>
案例分析
- 给一组元素注册事件
- 给小图片利用循环注册点击事件
- 当点击了这张图片,让页面背景改为当前的图片
- 核心算法:把当前图片src路径取出来,给body作为背景即可
<!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>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
margin:0px;
background: url(../img/bd1.jpg) no-repeat;
background-size:100% 100%;
background-attachment:fixed;
}
li {
list-style: none;
}
.baidu li {
float: left;
margin: 0 1px;
cursor: pointer;
}
.baidu img {
width: 100px;
}
</style>
</head>
<body>
<ul class="baidu">
<li><img src="../img/bd1.jpg"></li>
<li><img src="../img/bd2.jpeg"></li>
<li><img src="../img/bd3.jpg"></li>
<li><img src="../img/bd4.png"></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>
</body>
</html>
效果
仿照新浪财经网页效果 https://vip.stock.finance.sina.com.cn/mkt/
案例分析
- 鼠标经过 onmouseover 鼠标离开 onmouseout
- 核心思路:鼠标经过tr行,当前的行变背景颜色,鼠标离开去掉当前的背景颜色
- 注意:第一行不需要变换颜色
<!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>Document</title>
<style>
table {
/* 去掉td之间的空隙 */
border-spacing: 0;
width: 100%
}
thead th {
border-bottom: 1px solid #ACD3F2;
background: #D4EDFF;
}
tbody tr {
height: 30px;
}
tbody td {
border-bottom: 1px solid #d7d7d7;
font-size: 12px;
color: blue;
}
.bg {
background-color: #E6F3FC;
}
</style>
</head>
<body>
<div style="text-align: center;">
<table>
<thead>
<tr>
<th>代码</th>
<th>名称</th>
<th>最新价</th>
<th>涨跌额</th>
<th>涨跌幅</th>
<th>买入</th>
<th>卖出</th>
<th>昨收</th>
</tr>
</thead>
<tbody>
<tr>
<td>sh603061</td>
<td>N金海通</td>
<td>84.36</td>
<td>+25.78</td>
<td>+44.008%</td>
<td>84.36</td>
<td>0.00</td>
<td>58.58</td>
</tr>
<tr>
<td>sh688525</td>
<td>佰维存储</td>
<td>26.96</td>
<td>+4.49</td>
<td>+19.982%</td>
<td>26.96</td>
<td>0.00</td>
<td>22.47</td>
</tr>
<tr>
<td>sh688049</td>
<td>炬芯科技</td>
<td>36.51</td>
<td>+4.10</td>
<td>+12.650%</td>
<td>36.50</td>
<td>36.51</td>
<td>32.41</td>
</tr>
<tr>
<td>sh688230</td>
<td>芯导科技</td>
<td>70.08</td>
<td>+7.64</td>
<td>+12.236%</td>
<td>70.07</td>
<td>70.08</td>
<td>62.44</td>
</tr>
</tbody>
<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>
</table>
</div>
</body>
</html>
效果
案例分析
- 全选和取消全选做法:让下面所有复选框的checked属性(选中状态)跟随全选按钮即可
- 下面复选框全部选中,上面全选才能选中做法:给下面所有复选框绑定点击事件,每次点击都要循环查看下面所有复选框是否被选中,如果有一个没选中,上面全选就不选中
- 可以设置一个变量,来控制全选是否选中
<!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>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
.wrap {
width: 300px;
margin: 100px auto 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #c0c0c0;
width: 300px;
}
th,
td {
border: 1px solid #d0d0d0;
color: #404060;
padding: 10px;
}
th {
background-color: #09c;
font: bold 16px "微软雅黑";
color: #fff;
}
td {
font: 14px "微软雅黑";
}
tbody tr {
border-color: #f0f0f0;
}
tbody tr:hover {
cursor: pointer;
background-color: #fafafa;
}
</style>
</head>
<body>
<div class="wrap" style="text-align: center;">
<table>
<thead>
<tr>
<th>
<input type="checkbox" id="j_cbAll" />
</th>
<th>商品</th>
<th>价钱</th>
</tr>
</thead>
<tbody id="j_tb">
<tr>
<td>
<input type="checkbox" />
</td>
<td>iPhone8</td>
<td>8000</td>
</tr>
<tr>
<td>
<input type="checkbox" />
</td>
<td>iPad Pro</td>
<td>5000</td>
</tr>
<tr>
<td>
<input type="checkbox" />
</td>
<td>iPad Air</td>
<td>2000</td>
</tr>
<tr>
<td>
<input type="checkbox" />
</td>
<td>Apple Watch</td>
<td>2000</td>
</tr>
</tbody>
</table>
</div>
<script>
// 获取元素
var j_chAll = document.getElementById('j_cbAll');
var j_tbs = document.getElementById('j_tb').getElementsByTagName('input');
// 注册事件 处理程序
j_cbAll.onclick = function() {
// this.checked 可以得到复选框的选中状态 true就是选中 false就是未选中
for (var i = 0; i < j_tbs.length; i++) {
j_tbs[i].checked = this.checked;
}
}
// 下面复选框全部选中,上面全选才被选中
for (var i = 0; i < j_tbs.length; i++) {
j_tbs[i].onclick = function() {
// flag 控制全选按钮是否选中
var flag = true;
for (var i = 0; i < j_tbs.length; i++) {
if (!j_tbs[i].checked) {
flag = false;
break;
}
}
j_cbAll.checked = flag;
}
}
</script>
</body>
</html>
效果
获取属性值
区别:
设置属性值
移除属性
应用实例:https://dianqi.suning.com/?safp=
案例分析
- Tab栏切换有两个大的模块
- 上面的模块为导航栏,下面的模块为内容区
- 下面的模块内容会随上面的选项卡变化,所以下面的模块变化写到点击事件里面
- 规律:下面的模块显示内容和上面鼠标经过的选项卡一一对应,相互匹配
- 核心思路:给上面的所有li添加自定义属性,属性值从0开始编号
- 但鼠标经过li时,让内容模块显示对应的序号内容,其余隐藏(排他思想)
难点
- 首先是鼠标经过时图片和文字的切换,尤其是图片,实现还不够完整
- 因为写的样式有点多,所以最好一层层向下写好选择器
- 仿照写的,所有源码(除了框架)都是一步步仿照来的,没有任何取巧,才制作出这样的效果
- 默认会显示导航栏中第一个选项卡内容,这一点如果第一次实现需要了解下
观察细点就会发现有点瑕疵,和原效果有差距,但确实尽力只能做到这一步了
源码如下:
<!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>Document</title>
<style>
.hot-tab {
position: relative;
width: 840px;
margin: 10px auto;
background: #fff;
}
.hot-tab .tab-nav {
position: relative;;
width: 100%;
height: 86px;
margin-bottom: 20px;
background: #ccc;
border-bottom: 2px solid #3664db;
}
ul {
margin: 0;
padding: 0;
}
ul, li {
list-style: none;
}
.hot-tab .tab-nav li {
position: relative;
float: left;
width: 140px;
height: 86px;
text-align: center;
background: #fff;
}
.hot-tab .tab-nav li img {
display: inline-block;
width: 35px;
height: 35px;
margin-top: 10px;
margin-bottom: 5px;
}
.hot-tab .tab-nav li span {
display: block;
height: 22px;
color: #333;
overflow: hidden;
}
.hot-tab .tab-nav li em {
position: absolute;
display: none;
content: '';
width: 0;
height: 0;
bottom: -2px;
left: 50%;
margin-left: -12px;
border-left: 12px solid transparent;
border-right: 12px solid transparent;
border-bottom: 8px solid #fff;
}
.hot-tab .tab-content-wrap {
position: relative;
}
.hot-tab .tab-content-wrap .item {
position: relative;
width: 1190px;
height: 340px;
left: 0;
top: 0;
overflow: hidden;
display: none;
}
.hot-tab .tab-content-wrap .defatult_c {
display: block;
}
.hot-tab .tab-nav .default_n {
background: #3664db;
}
.hot-tab .tab-nav .default_n span {
color: #fff;
}
.hot-tab .tab-nav .cur {
background: #3664db;
}
.hot-tab .tab-nav .cur span {
color: #fff;
}
.hot-tab .tab-nav .cur em {
display: block;
}
</style>
</head>
<body>
<div class="hot-tab">
<div class="tab-nav">
<ul class="clearfix">
<li class="default_n">
<img src="../img/tab-hot-h.png" c-src="../img/tab-hot.png" d-src="../img/tab-hot-h.png" alt="今日必抢">
<span>今日必抢</span>
<em></em>
</li>
<li>
<img src="../img/tab-kt.png" c-src="../img/tab-kt.png" d-src="../img/tab-kt-h.png" alt="空调">
<span>空调</span>
<em></em>
</li>
<li>
<img src="../img/hot-ds.png" c-src="../img/hot-ds.png" d-src="../img/hot-ds-h.png" alt="电视">
<span>电视</span>
<em></em>
</li>
<li>
<img src="../img/hot-rs.png" c-src="../img/hot-rs.png" d-src="../img/hot-rs-h.png" alt="热水器">
<span>热水器</span>
<em></em>
</li>
<li>
<img src="../img/hot-bx.png" c-src="../img/hot-bx.png" d-src="../img/hot-bx-h.png" alt="冰箱">
<span>冰箱</span>
<em></em>
</li>
<li>
<img src="../img/hot-xy.png" c-src="../img/hot-xy.png" d-src="../img/hot-xy-h.png" alt="洗衣机">
<span>洗衣机</span>
<em></em>
</li>
</ul>
</div>
<div class="tab-content-wrap">
<div class="item defatult_c">今日必抢模块内容</div>
<div class="item">空调模块内容</div>
<div class="item">电视模块内容</div>
<div class="item">热水器模块内容</div>
<div class="item">冰箱模块内容</div>
<div class="item">洗衣机模块内容</div>
</div>
</div>
<script>
// 获取元素
var tab_nav = document.querySelector('.tab-nav');
var lis = tab_nav.querySelectorAll('li');
var items = document.querySelectorAll('.item');
// for循环绑定鼠标经过和离开事件
for (var i = 0; i < lis.length; i++) {
// 开始给6个li 设置索引号
lis[i].setAttribute('index', i);
lis[i].onmouseover = function() {
// 干掉其他人
for (var i = 0; i < lis.length; i++) {
lis[i].className = '';
}
this.className = 'cur';
var img = this.querySelector('img');
img.src = img.getAttribute('d-src');
// 显示内容模块
var index = this.getAttribute('index');
// 干掉所有人
for (var i = 0; i < items.length; i++) {
items[i].style.display = 'none';
}
// 留下我自己
items[index].style.display = 'block';
}
lis[i].onmouseout = function() {
var span = this.querySelector('span');
var img = this.querySelector('img');
img.src = img.getAttribute('c-src');
}
}
</script>
</body>
</html>
最大收获就是有了仿照网页的经验,之前有,但都是跟着视频里老师一步步敲的,这次从头到尾都是独立分析的,其次对之前的知识进行了一次回顾,还阔以…
自定义属性目的:为了保存并使用数据,有些数据可以保存到页面中而不用保存到数据库中
但有些自定义属性容易引起歧义,不容易判断是元素的内置属性还是自定义属性
H5规定自定义属性data-开头作为属性名且赋值,只能
获取H5自定义属性
<!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>Document</title>
</head>
<body>
<div getTime="20" data-index="2" data-list-name="andy"></div>
<script>
var div = document.querySelector('div');
console.log(div.getAttribute('getTime'));
// h5新增的获取自定义属性的方法 只能获取data-开头的
console.log(div.dataset);
console.log(div.dataset.index);
console.log(div.dataset['index']);
// 如果自定义属性里面有多个-链接的单词,获取时采用驼峰命名法
console.log(div.dataset.listName);
</script>
</body>
</html>
获取元素通常使用两种方式
利用DOM提供的方法获取元素
逻辑性不强,繁琐
利用节点层级关系获取元素
这两种方式都可以获取元素节点,但节点操作更简单
网页中所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node来表示
HTML DOM树中所有节点均可通过JavaScript进行访问
一般来讲,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性
在实际开发中,节点操作主要操作元素节点
利用DOM树可以把节点划分为不同的层级关系,常见的父子兄层级关系
parentNode.childNodes(标准)
和parentNode.children(非标准)
parentNode.children
是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回
虽然parentNode.children
是一个非标准,但得到了各浏览器的支持,因而可以放心使用
<!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>Document</title>
</head>
<body>
<!-- 节点的优点 -->
<div>我是div</div>
<span>我是span</span>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<div class="box">
<span class="erweima">x</span>
</div>
<script>
var ul = document.querySelector('ul');
// 子节点 childNodes 所有的子节点 包含 元素节点、文本节点等
console.log(ul.childNodes);
console.log(ul.childNodes[0].nodeType);
console.log(ul.childNodes[1].nodeType);
// children 获取所有的子元素节点 实际开发常用的
console.log(ul.children);
</script>
</body>
</html>
parentNode.firstChild
返回第一个子节点,找不到则返回null。支持所有节点
parentNode.lastChild
返回最后一个子节点,找不到则返回null。支持所有节点
parentNode.firstElementChild
返回第一个子元素节点,找不到则返回null
parentNode.lastElementChild
返回最后一个元素节点,找不到则返回null
注意: 这两个方法有兼容性问题,IE9以上才支持
实际开发
效果
案例分析
- 导航栏里面的li都要有鼠标经过效果,所以需要循环注册鼠标事件
- 核心原理:当鼠标经过li里面的 第二个孩子 ul显示,当鼠标离开,ul隐藏
源码如下
<!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>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
a {
text-decoration: none;
font-size: 14px;
}
.nav {
margin: 100px;
}
ul, li {
list-style: none;
}
.nav>li {
position: relative;
float: left;
width: 120px;
height: 40px;
text-align: center;
}
.nav li a {
display: block;
width: 100%;
height: 100%;
line-height: 40px;
color: #333;
}
.nav .arrow {
display: inline-block;
width: 8px;
height: 5px;
margin: 0 0 0 5px;
font-size: 12px;
line-height: 13px;
background: url(/第三阶段/img/xl.png) 0 -977px no-repeat; /* 前一个代表靠左距离值(可为正可为负),第二个数值代表靠上距离值(可为正可为负) */
}
.nav>li>a:hover {
color: #ff8400;
background-color: #EDEEF0
}
.nav ul {
display: none;
border-left: 1px solid #fecc5b;
border-right: 1px solid #fecc5b;
}
.nav ul li {
border-bottom: 1px solid #fecc5b;
}
.nav ul li:hover {
background: #FFF5DA;
}
</style>
</head>
<body>
<ul class="nav">
<li>
<a href="#">
微博
<span class="arrow"></span>
</a>
<ul>
<li>
<a href="">私信</a>
</li>
<li>
<a href="">评论</a>
</li>
<li>
<a href="">@我</a>
</li>
</ul>
</li>
<li>
<a href="#">
博客
<span class="arrow"></span>
</a>
<ul>
<li>
<a href="">博客评论</a>
</li>
<li>
<a href="">未读提醒</a>
</li>
</ul>
</li>
<li>
<a href="#">
邮箱
<span class="arrow"></span>
</a>
<ul>
<li>
<a href="">免费邮箱</a>
</li>
<li>
<a href="">VIP邮箱</a>
</li>
<li>
<a href="">企业邮箱</a>
</li>
<li>
<a href="">新浪邮箱客户端</a>
</li>
</ul>
</li>
</ul>
<script>
// 获取元素
var nav = document.querySelector('.nav');
var lis = nav.children; // 得到3个li
// 循环注册事件
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>
</html>
node.nextSibling
返回当前元素的下一个兄弟节点,找不到返回null(包含所有节点)
node.previousSibling
返回当前元素上一个兄弟节点,找不到则返回null(包含所有节点)
node.nextElementSibling
返回当前元素下一个兄弟元素节点,找不到则返回null
node.previousElementSibling
返回当前元素上一个兄弟元素节点,找不到则返回null
注意: 这两个方法有兼容性问题,IE9以上才支持
如何解决兼容性问题
封装一个兼容性函数
function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {
if (el.nodeType === 1) {
return el;
}
}
return null;
}
document.createElement('tagName')
方法创建由tagName指定的HTML元素。因为这些元素原先不存在,是根据需求动态生成的,所以也称为动态创建元素节点
node.appendChild(child)
方法将一个节点添加到指定父节点的子节点列表末尾。类似于css里面的after伪元素
node.insertBefore(child,指定元素)
方法将一个节点添加到父节点的指定子节点前面。类似于css里面的before伪元素
<!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>Document</title>
</head>
<body>
<ul>
<li>123</li>
</ul>
<script>
// 创建节点之元素节点
var li = document.createElement('li');
// 添加节点
var ul = document.querySelector('ul');
ul.appendChild(li);
// 添加节点 node.insertBefore(child, 指定元素)
var lili = document.createElement('li');
ul.insertBefore(lili, ul.children[0]);
// 页面添加一个新元素:1. 创建元素 2. 添加元素
</script>
</body>
</html>
- 核心思路:点击按钮之后,就动态创建一个p,添加到div里面
- 创建p的同时,把文本域里面的值通过p.innerHTML赋值给p
- 如果想要新的留言后面显示就用apendChild 如果想要前面的显示就用insertBefore
效果
<!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>留言板</title>
<link rel="stylesheet" href="./CSS/ly.css">
</head>
<body>
<!-- 发布留言的主题 -->
<div class="wrap">
<div class="wrap-head">
<div class="head-logo">
<img src="/第三阶段/img/logo.png" alt="logo">
</div>
<div class="head-txt">
<a class="title-txt" href="https://mp.weixin.qq.com/s/0pdLlt_754Vehg5O1_K1xw">真经亦难趣</a>
</div>
</div>
<div class="main-txt">
<textarea rows="" cols="" class="main-area"></textarea>
</div>
<div class="wrap-footer">
<div class="wrap-icon">
<ul>
<li>
<img src="/第三阶段/img/bq.png" alt="">
<a href="javascript:void(0)">表情</a>
</li>
<li>
<img src="/第三阶段/img/tp.png" alt="">
<a href="javascript:void(0)">图片</a>
</li>
<li>
<img src="/第三阶段/img/sp.png" alt="">
<a href="javascript:void(0)">视频</a>
</li>
<li>
<img src="/第三阶段/img/wz.png" alt="">
<a href="javascript:void(0)">文章</a>
</li>
</ul>
</div>
<div class="wrap-footer-btn">
<div class="release-btn">
<button>发布</button>
</div>
</div>
</div>
</div>
<!-- 显示留言主体 -->
<div class="show">
<div class="show-txt">
</div>
</div>
<script>
// 获取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var show = document.querySelector('.show');
var showTxt = document.querySelector('.show-txt');
var showTime = document.querySelector('.show-time');
// 注册事件
btn.onclick = function() {
if (text.value == '') {
alert('您没有输入内容');
return false;
} else {
var date = new Date();
show.style.display = 'block';
var p = document.createElement('p');
var span = document.createElement('span');
var i = document.createComment('i');
p.innerHTML = text.value + "x";
text.value = "";
span.innerHTML = date;
showTxt.insertBefore(p, showTxt.children[0]);
showTxt.insertBefore(span, showTxt.children[1]);
}
}
</script>
</body>
</html>
CSS源码
* {
margin: 0;
padding: 0;
}
a {
text-decoration: none;
font-size: 14px;
}
ul {
list-style: none;
}
/* 最外层 */
.wrap {
width: 1000px;
height: 245px;
margin: 20px auto;
border-radius: 4px;
border: 1px solid #ddd;
padding: 0 10px;
}
.wrap .wrap-head {
width: 100%;
height: 40px;
padding-top:4px;
overflow: hidden;
}
.wrap .wrap-head .head-logo {
width: 40%;
float: left;
}
.wrap .wrap-head .head-logo img {
width: 60px;
height: 60px;
}
.wrap .wrap-head .head-txt {
padding: 20px 0;
width: 60%;
float: right;
}
.wrap .wrap-head .head-txt a {
color: #3C97EF;
text-align: right;
display: block;
width: 100%;
}
/* 内层设计,输入框 */
.wrap .main-txt {
border: 1px solid #ccc;
width: 99%;
height: 125px;
margin: 6px 0 0;
padding: 5px;
box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.15) inset;
}
.wrap .main-txt textarea {
border: none;
width: 100%;
height: 66px;
outline: none;
resize: none;
color: #333;
}
/* 下层设计 */
.wrap .wrap-footer {
width: 100%;
height: 40px;
margin: 6px 0;
overflow: hidden;
}
.wrap .wrap-footer .wrap-icon {
width: 65%;
float: left;
margin-top: 10px;
}
.wrap .wrap-footer .wrap-icon ul li {
display: inline-block;
margin-right: 15px;
cursor: pointer;
}
.wrap .wrap-icon a {
font-size: 12px;
color: #333;
height: 20px;
margin-left: 5px;
display: block;
width: 25px;
float: right;
line-height: 20px;
}
.wrap .wrap-footer .wrap-icon a:hover {
color: #eb7350;
}
.wrap .wrap-footer .wrap-icon img {
width: 20px;
height: 20px;
}
.wrap .wrap-footer .wrap-footer-btn {
width: 35%;
float: right;
overflow: hidden;
margin-top: 5px;
}
.wrap .wrap-footer .wrap-footer-btn .release-btn {
float: right;
}
.wrap .wrap-footer .wrap-footer-btn button {
position: relative;
transition: background 400ms;
color: #fff;
background-color: #6A84DA;
padding: 0.2rem 1rem;
font-size: 1.2rem;
overflow: hidden;
outline: 0;
border: 0;
border-radius: 0.25rem;
box-shadow: 0 0 0.6rem rgba(0, 0, 0, 0.3);
cursor: pointer;
z-index: 1;
}
.wrap .wrap-footer .wrap-footer-btn button::before {
content: "";
position: absolute;
z-index: -1;
top: 50%;
left: 50%;
width: 1rem;
height: 1rem;
transform: translate3d(-50%,-50%,0) scale(0,0);
border-radius: 0.4rem;
background-color: #7886af;
transform-origin: center;
transition: ease-in-out .5s;
}
.wrap .wrap-footer .wrap-footer-btn button:hover::before {
transform: translate3d(-50%,-50%,0) scale(15,15);
}
/* 后期添加的留言框 */
.show {
width: 1000px;
margin: 20px auto;
display: none;
}
.show .show-txt {
width: 100%;
color: #444;
border-radius: 4px;
}
.show .show-txt p {
word-wrap: break-word;
margin-top: 15px;
padding-left: 15px;
padding-right: 25px;
border: 1px solid #ddd;
position: relative;
}
.show .show-txt p a {
position: absolute;
color: #aaa;
top: 0;
right: 0;
}
.show .show-txt span {
font-size: 12px;
color: #808080;
margin-top: 10px;
}
node.removeChild(child)
方法从DOM中删除一个子节点,返回删除的节点
案例分析
- 当把文本域里面的值赋值给p的时候,就多添加一个删除的链接
- 需要把所有的链接获取过来,当点击链接的时候,删除当前链接所在的p
基于简单版发布留言案例进行修改
效果
<!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>留言板</title>
<link rel="stylesheet" href="./CSS/ly.css">
</head>
<body>
<!-- 发布留言的主题 -->
<div class="wrap">
<div class="wrap-head">
<div class="head-logo">
<img src="/第三阶段/img/logo.png" alt="logo">
</div>
<div class="head-txt">
<a class="title-txt" href="https://mp.weixin.qq.com/s/0pdLlt_754Vehg5O1_K1xw">真经亦难趣</a>
</div>
</div>
<div class="main-txt">
<textarea rows="" cols="" class="main-area"></textarea>
</div>
<div class="wrap-footer">
<div class="wrap-icon">
<ul>
<li>
<img src="/第三阶段/img/bq.png" alt="">
<a href="javascript:void(0)">表情</a>
</li>
<li>
<img src="/第三阶段/img/tp.png" alt="">
<a href="javascript:void(0)">图片</a>
</li>
<li>
<img src="/第三阶段/img/sp.png" alt="">
<a href="javascript:void(0)">视频</a>
</li>
<li>
<img src="/第三阶段/img/wz.png" alt="">
<a href="javascript:void(0)">文章</a>
</li>
</ul>
</div>
<div class="wrap-footer-btn">
<div class="release-btn">
<button>发布</button>
</div>
</div>
</div>
</div>
<!-- 显示留言主体 -->
<div class="show">
<div class="show-txt">
</div>
</div>
<script>
// 获取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var show = document.querySelector('.show');
var showTxt = document.querySelector('.show-txt');
var showTime = document.querySelector('.show-time');
// 注册事件
btn.onclick = function() {
if (text.value == '') {
alert('您没有输入内容');
return false;
} else {
var date = new Date();
show.style.display = 'block';
var p = document.createElement('p');
var span = document.createElement('span');
var i = document.createComment('i');
p.innerHTML = text.value + '
' + "x";
text.value = "";
span.innerHTML = date;
showTxt.insertBefore(p, showTxt.children[0]);
p.appendChild(span, p.children[0]);
var as = showTxt.querySelectorAll('a');
// 注册删除事件
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
showTxt.removeChild(this.parentNode);
}
}
}
}
</script>
</body>
</html>
CSS源码
* {
margin: 0;
padding: 0;
}
a {
text-decoration: none;
font-size: 14px;
}
ul {
list-style: none;
}
/* 最外层 */
.wrap {
width: 1000px;
height: 245px;
margin: 20px auto;
border-radius: 4px;
border: 1px solid #ddd;
padding: 0 10px;
}
.wrap .wrap-head {
width: 100%;
height: 40px;
padding-top:4px;
overflow: hidden;
}
.wrap .wrap-head .head-logo {
width: 40%;
float: left;
}
.wrap .wrap-head .head-logo img {
width: 60px;
height: 60px;
}
.wrap .wrap-head .head-txt {
padding: 20px 0;
width: 60%;
float: right;
}
.wrap .wrap-head .head-txt a {
color: #3C97EF;
text-align: right;
display: block;
width: 100%;
}
/* 内层设计,输入框 */
.wrap .main-txt {
border: 1px solid #ccc;
width: 99%;
height: 125px;
margin: 6px 0 0;
padding: 5px;
box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.15) inset;
}
.wrap .main-txt textarea {
border: none;
width: 100%;
height: 66px;
outline: none;
resize: none;
color: #333;
}
/* 下层设计 */
.wrap .wrap-footer {
width: 100%;
height: 40px;
margin: 6px 0;
overflow: hidden;
}
.wrap .wrap-footer .wrap-icon {
width: 65%;
float: left;
margin-top: 10px;
}
.wrap .wrap-footer .wrap-icon ul li {
display: inline-block;
margin-right: 15px;
cursor: pointer;
}
.wrap .wrap-icon a {
font-size: 12px;
color: #333;
height: 20px;
margin-left: 5px;
display: block;
width: 25px;
float: right;
line-height: 20px;
}
.wrap .wrap-footer .wrap-icon a:hover {
color: #eb7350;
}
.wrap .wrap-footer .wrap-icon img {
width: 20px;
height: 20px;
}
.wrap .wrap-footer .wrap-footer-btn {
width: 35%;
float: right;
overflow: hidden;
margin-top: 5px;
}
.wrap .wrap-footer .wrap-footer-btn .release-btn {
float: right;
}
.wrap .wrap-footer .wrap-footer-btn button {
position: relative;
transition: background 400ms;
color: #fff;
background-color: #6A84DA;
padding: 0.2rem 1rem;
font-size: 1.2rem;
overflow: hidden;
outline: 0;
border: 0;
border-radius: 0.25rem;
box-shadow: 0 0 0.6rem rgba(0, 0, 0, 0.3);
cursor: pointer;
z-index: 1;
}
.wrap .wrap-footer .wrap-footer-btn button::before {
content: "";
position: absolute;
z-index: -1;
top: 50%;
left: 50%;
width: 1rem;
height: 1rem;
transform: translate3d(-50%,-50%,0) scale(0,0);
border-radius: 0.4rem;
background-color: #7886af;
transform-origin: center;
transition: ease-in-out .5s;
}
.wrap .wrap-footer .wrap-footer-btn button:hover::before {
transform: translate3d(-50%,-50%,0) scale(15,15);
}
/* 后期添加的留言框 */
.show {
width: 1000px;
margin: 20px auto;
display: none;
}
.show .show-txt {
width: 100%;
color: #444;
border-radius: 4px;
}
.show .show-txt p {
word-wrap: break-word;
margin-top: 15px;
padding-left: 15px;
padding-right: 25px;
border: 1px solid #ddd;
position: relative;
}
.show .show-txt p a {
position: absolute;
color: #aaa;
top: 0;
right: 0;
}
.show .show-txt p span {
font-size: 12px;
color: #808080;
margin-top: 10px;
}
node.cloneNode()
方法返回方法调用者(节点)的一个副本,该副本被称为克隆节点/拷贝节点
注意: 如果括号参数为空或false,则为浅拷贝,即只克隆复制节点本身,不克隆里面的子节点
案例分析
- 因为表中的数据是动态的,需要JS动态生成,这里模拟数据,自己定义数据。数据采取对象形式存储
- 所有数据都是放到tbody中的行里面
- 行数对应对象数
- 最后一列单元格是删除,需要单独创建单元格
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>
table {
width: 500px;
margin: 100px auto;
border-collapse: collapse;
text-align: center;
}
td,
th {
border: 1px solid #333;
}
thead tr {
height: 40px;
background-color: #ccc;
}
style>
head>
<body>
<table cellspacing="0">
<thead>
<tr>
<th>姓名th>
<th>科目th>
<th>成绩th>
<th>操作th>
tr>
thead>
<tbody>
tbody>
table>
<script>
var datas = [{
name: '魏珞樱',
subject: 'JavaScript',
score: 100
},{
name: '弘历',
subject: 'JavaScript',
score: 98
},{
name: '傅恒',
subject: 'JavaScript',
score: 99
},{
name: '明玉',
subject: 'JavaScript',
score: 88
}];
var tbody = document.querySelector('tbody');
for (var i = 0; i < datas.length; i++) {
var tr = document.createElement('tr');
tbody.append(tr);
// 行里面创建单元格 单元格的数量取决于每个对象里面的属性个数
for (var k in datas[i]) {
// 创建单元格
var td = document.createElement('td');
// 把对象里面的属性值 给 td
td.innerHTML = datas[i][k];
tr.appendChild(td);
}
// 创建最后一列单元格
var td = document.createElement('td');
td.innerHTML = '删除';
tr.appendChild(td);
}
// 获取所有的 a元素
var as = document.querySelectorAll('a');
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
// 找到 a元素的爷爷
tbody.removeChild(this.parentNode.parentNode);
}
}
script>
body>
html>
效果
注意:
document.write是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
效果
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>
head>
<body>
<button>点击button>
<p>abcp>
<script>
// 三种创建元素的方式
var btn = document.querySelector('button');
btn.onclick = function() {
document.write('123');
}
script>
body>
html>
innerHTML
是将内容写入某个DOM节点,不会导致页面全部重绘
innerTHML
创建多个元素效率更高(不拼接字符串,采取数组形式拼接),结构稍微复杂,但效率更高
createElement()
创建多个元素效率稍低一点,但结构更清晰
总结:不同浏览器下,innerHTML
效率要比createElement
高
对于dom操作,主要针对于元素的操作,有创建、增、删、改、查、属性操作、事件操作
给元素添加事件,称为注册事件或绑定事件
注册事件有两种方式:传统方式和方法监听注册方法
传统注册方式
方法监听注册方式
eventTarget.addEventListener(type, listener[, useCapture])
eventTarget.addEventListener()
方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数
该方法接收三个参数:
eventTarget.attachEvent()
方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定事件时,指定的回调函数就会被执行
该方法接收两个参数:
兼容性处理的原则:首先照顾大多数浏览器,再处理特殊浏览器
<!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>Document</title>
</head>
<body>
<button>传统注册事件</button>
<button>方法监听注册事件</button>
<button>ie9 attachEvent</button>
<script>
var btns = document.querySelectorAll('button');
// 传统方式注册事件
btns[0].onclick = function() {
alert('hi');
}
btns[0].onclick = function() {
alert('how are you');
}
// 事件监听注册事件 里面的事件类型是字符串 必定加引号
btns[1].addEventListener('click', function() {
alert(22);
})
btns[1].addEventListener('click', function() {
alert(33);
})
// attachEvent ie9以前的版本支持
btns[2].attachEvent('onclick', function() {
alert(11);
})
</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>Document</title>
<style>
div {
width: 100px;
height: 100px;
background: pink;
}
</style>
</head>
<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) // 里面的fn 不需要调用加小括号
function fn() {
alert(22);
divs[1].removeEventListener('click', fn);
}
divs[2].attachEvent('onclick', fn1);
function fn1() {
alert(33);
divs[2].datachEvent('onclick', fn1);
}
</script>
</body>
</html>
事件流描述的是从页面中接收事件的顺序
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
比如给一个div注册点击事件:
DOM事件流分为三个阶段:
向水里仍一块石头,首先它会有一个下降的过程,这个过程可以理解为最顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点(最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
注意:
<!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>Document</title>
<style>
.father {
overflow: hidden;
width: 300px;
height: 300px;
margin: 100px auto;
background-color: pink;
text-align: center;
}
.son {
width: 200px;
height: 200px;
margin: 50px;
background-color: purple;
line-height: 200px;
color: #fff;
}
</style>
</head>
<body>
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
// 捕获阶段 document -> html -> body -> father -> son
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
}, true)
var father = document.querySelector('.father');
father.addEventListener('click', function(){
alert('father');
}, true)
// 冒泡阶段
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
}, false)
var father = document.querySelector('.father');
father.addEventListener('click', function(){
alert('father');
}, false)
document.addEventListener('click', function() {
alert('document');
}, false)
</script>
</body>
</html>
效果
官方释义:event对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态
简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,它有很多属性和方法
比如:
这个event是个形参,系统帮助我们设定为事件对象,不需要传递实参过去
当注册事件时,event对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)
事件对象本身的获取存在兼容性问题:
解决:e = e || window.event;
<!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>Document</title>
</head>
<body>
<div>123</div>
<script>
// 事件对象
var div = document.querySelector('div');
// 事件对象 是 事件的一系列相关数据的集合 跟事件相关 比如鼠标点击里面就包含了鼠标的相关信息,如鼠标坐标;如果是键盘事件,里面就包含键盘的相关信息,如判断用户按下了那个键
div.onclick = function(event) {
console.log(event);
}
// 事件对象名称可自定义
div.addEventListener('click', function(e) {
console.log(e);
})
// 事件对象也是有兼容性问题的
</script>
</body>
</html>
事件对象属性方法 | 说明 |
---|---|
e.target | 返回触发事件的对象 标准 |
e.srcElement | 返回触发事件的对象 非标准 ie6~8使用 |
e.type | 返回事件的类型 比如click mouseover 不带on |
e.cancelBubble | 该属性阻止冒泡 非标准 ie6~8使用 |
e.returnValue | 该属性 阻止默认事件(默认行为)非标准 ie6~8使用 比如不让链接跳转 |
e.preventDefault() | 该方法 阻止默认事件(默认行为)标准 比如不让链接跳转 |
e.stopPropagation() | 阻止冒泡 标准 |
<!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>Document</title>
<style>
div {
height: 100px;
width: 100px;
background: pink;
}
</style>
</head>
<body>
<div>123</div>
<ul>
<li>abc</li>
<li>abc</li>
<li>abc</li>
</ul>
<script>
// 常见事件对象的属性和方法
var div = document.querySelector('div');
// e.target 返回的是触发事件对象(元素)this 返回的是绑定事件对象(元素)
div.addEventListener('click', function(e) {
console.log(e.target);
console.log((this));
})
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
// 给ul 绑定事件 那么 this 就指向ul
console.log(this);
console.log(e.target);
})
// 了解兼容性
// div.onclick = function(e) {
// e = e || window.event;
// var target = e.target || e.srcElement;
// console.log(target);
// }
</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>Document</title>
</head>
<body>
<div>123</div>
<a href="https://www.baidu.com">百度</a>
<form action="https://www.baidu.com">
<input type="submit" value="提交" name="sub">
</form>
<script>
// 返回事件类型
var div = document.querySelector('div');
div.addEventListener('click', fn);
div.addEventListener('mouseover', fn);
div.addEventListener('mouseout', fn);
function fn(e) {
console.log(e.type);
}
// 阻止默认行为(事件)让链接不跳转 或 让提交按钮先不提交
var a = document.querySelector('a');
a.addEventListener('click', function(e) {
e.preventDefault();
})
a.onclick = function(e) {
// 普通浏览器 e.preventDefault(); 方法
// e.preventDefault();
// 低版本浏览器 ie6~8 returnValue 属性
// e.returnValue;
// 可以利用 return false 来阻止默认行为 无兼容性问题 只限于传统注册方式
return false;
}
</script>
</body>
</html>
事件冒泡:开始时由最具体元素接收,然后逐级向上传播到DOM最顶层节点
事件冒泡本身的特性:有利有弊
阻止事件冒泡
<!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>Document</title>
<style>
.father {
overflow: hidden;
width: 300px;
height: 300px;
margin: 100px auto;
background-color: pink;
text-align: center;
}
.son {
width: 200px;
height: 200px;
margin: 50px;
background-color: purple;
line-height: 200px;
color: #fff;
}
</style>
</head>
<body>
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
// 冒泡阶段
var son = document.querySelector('.son');
son.addEventListener('click', function(e) {
alert('son');
e.stopPropagation();
}, false)
var father = document.querySelector('.father');
father.addEventListener('click', function(){
alert('father');
}, false)
document.addEventListener('click', function() {
alert('document');
}, false)
</script>
</body>
</html>
事件冒泡本身的特性,会带来坏处,也会带来好处,需要灵活掌握
事件委托称为事件代理,在jQuery里面称为事件委派
事件委托的原理
不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点
事件委托的作用:只操作一次DOM,提高了程序的性能
<!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>Document</title>
</head>
<body>
<ul>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
</ul>
<script>
// 事件委托的核心原理:给父节点添加监听器,利用事件冒泡影响每一个子节点
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
alert('知否知否,点我应有弹框在手!');
e.target.style.background = 'pink';
})
</script>
</body>
</html>
contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
<!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>Document</title>
</head>
<body>
我是一段不愿意分享的文字
<script>
// 禁用右键菜单
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
})
// 禁止选中文字
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
</script>
</body>
</html>
event对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段主要用鼠标事件对象MouseEvent
和键盘事件对象KeyboardEvent
鼠标事件对象 | 说明 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX | 返回鼠标相对于文档页面的X坐标 IE9+ 支持 |
e.pageY | 返回鼠标相对于文档页面的Y坐标 IE9+ 支持 |
e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的Y坐标 |
<!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>Document</title>
</head>
<body>
<script>
// 鼠标事件对象 MouseEvent
document.addEventListener('click', function(e) {
console.log(e);
// client 鼠标在可视区的x和y坐标
console.log(e.clientX);
console.log(e.clientY);
console.log('--------------------');
// page 鼠标在页面文档的x和y坐标
console.log(e.pageX);
console.log(e.pageY);
console.log('-------------------');
// screen 鼠标在电脑屏幕的x和y坐标
console.log(e.screenX);
console.log(e.screenY);
})
</script>
</body>
</html>
案例分析
- 鼠标不断的移动,使用鼠标移动事件:mousemove
- 在页面中移动,给document注册事件
- 图片要移动距离,而且不占位置,使用绝对定位即可
- 核心原理:每次鼠标移动,都会获得最新的鼠标坐标,把这个x和y坐标作为图片的top和left值就可以移动图片了
<!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>Document</title>
<style>
img {
position: absolute;
}
</style>
</head>
<body>
<img src="/第三阶段/img/angel.gif" alt="">
<script>
var pic = document.querySelector('img');
document.addEventListener('mousemove', function(e) {
var x = e.pageX;
var y = e.pageY;
console.log('x坐标是' + x, 'y坐标是' + y);
// 坐标单位莫忘添
pic.style.left = x - 45 + 'px';
pic.style.top = y - 40 + 'px';
});
</script>
</body>
</html>
事件除了使用鼠标触发,还可以使用键盘触发
键盘事件 | 触发条件 |
---|---|
onkeyup | 某个键盘按键被松开时触发 |
onkeydown | 某个键盘按键被按下时触发 |
onkeypress | 某个键盘按键被按下时 触发 但不识别功能键 比如:ctrl shift 箭头等 |
注意:
<!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>Document</title>
</head>
<body>
<script>
// keyup 按键弹起时触发
document.addEventListener('keyup', function() {
console.log('我弹起了');
})
// keydown 按键按下时触发
document.addEventListener('keydown', function() {
console.log('我按下了down');
})
// keypress 按键按下时触发
document.addEventListener('keypress', function() {
console.log('我按下了press');
})
</script>
</body>
</html>
键盘事件对象 属性 | 说明 |
---|---|
keyCode | 返回改键的ASCII值 |
注意: onkeydown 和 onkeyup 不区分字母大小写,onkeypress区分字母大小写
以下是搬运@梦里逆天 博主 所列出的按键与之对应的ASCII值
字母和数字键的键码值(keyCode) | |||||||
---|---|---|---|---|---|---|---|
按键 | 键码 | 按键 | 键码 | 按键 | 键码 | 按键 | 键码 |
A | 65 | J | 74 | S | 83 | 1 | 49 |
B | 66 | K | 75 | T | 84 | 2 | 50 |
C | 67 | L | 76 | U | 85 | 3 | 51 |
D | 68 | M | 77 | V | 86 | 4 | 52 |
E | 69 | N | 78 | W | 87 | 5 | 53 |
F | 70 | O | 79 | X | 88 | 6 | 54 |
G | 71 | P | 80 | Y | 89 | 7 | 55 |
H | 72 | Q | 81 | Z | 90 | 8 | 56 |
I | 73 | R | 82 | 0 | 48 | 9 | 57 |
数字键盘上的各键键码值(keyCode) | 功能键键码值(keyCode) | ||||||
---|---|---|---|---|---|---|---|
按键 | 键码 | 按键 | 键码 | 按键 | 键码 | 按键 | 键码 |
0 | 96 | 8 | 104 | F1 | 112 | F9 | 120 |
1 | 97 | 9 | 105 | F2 | 113 | F10 | 121 |
2 | 98 | * | 106 | F3 | 114 | F11 | 122 |
3 | 99 | + | 107 | F4 | 115 | F12 | 123 |
4 | 100 | Enter | 108 | F5 | 116 | ||
5 | 101 | - | 109 | F6 | 117 | ||
6 | 102 | . | 110 | F7 | 118 | ||
7 | 103 | / | 111 | F8 | 119 |
控制键键码值(keyCode) | |||||||
---|---|---|---|---|---|---|---|
按键 | 键码 | 按键 | 键码 | 按键 | 键码 | 按键 | 键码 |
BackSpace | 8 | Esc | 27 | Right Arrow | 39 | -_ | 189 |
Tab | 9 | Spacebar | 32 | Dw Arrow | 40 | .> | 190 |
Clear | 12 | Page Up | 33 | Insert | 45 | /? | 191 |
Enter | 13 | Page Down | 34 | Delete | 46 | `~ | 192 |
Shift | 16 | End | 35 | Num Lock | 144 | [{ | 219 |
Control | 17 | Home | 36 | ;: | 186 | \| | 220 |
Alt | 18 | Left Arrow | 37 | =+ | 187 | ]} | 221 |
Cape Lock | 20 | Up Arrow | 38 | ,< | 188 | '" | 222 |
多媒体键码值(keyCode) | |||
---|---|---|---|
按键 | 键码 | 按键 | 键码 |
音量加 | 175 | 浏览器 | 172 |
音量减 | 174 | 邮件 | 180 |
停止 | 179 | 搜索 | 170 |
静音 | 173 | 收藏 | 171 |
<!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>Document</title>
</head>
<body>
<script>
// 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
// keyup 和 keydown 事件不区分字母大小写 a 和 A 得到的都是65
document.addEventListener('keyup', function(e) {
console.log('up:' + e.keyCode);
if (e.keyCode === 65) {
alert('您按下了a键')
} else {
alert('您没有按下a键')
}
})
document.addEventListener('keypress', function(e) {
console.log('press:' + e.keyCode);
})
</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>Document</title>
</head>
<body>
<input type="text">
<script>
var search = document.querySelector('input');
document.addEventListener('keyup', function(e) {
if (e.keyCode === 83) {
search.focus();
}
})
</script>
</body>
</html>
案例分析
注意: keydown和keypress在文本框里面的特点:两个事件触发的时候,文字还没有落入文本框中
应用实例:
源码如下:
<!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>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.search {
position: relative;
width: 178px;
margin: 100px;
}
.con {
display: none;
position: absolute;
top: -40px;
width: 171px;
border: 1px solid rgba(0, 0, 0, .2);
box-shadow: 0 2px 4px rgba(0, 0, 0, .2);
padding: 5px 0;
font-size: 18px;
line-height: 20px;
color: #333;
}
.con::before {
content: '';
width: 0;
height: 0;
position: absolute;
top: 28px;
left: 18px;
border: 8px solid #000;
border-style: solid dashed dashed;
border-color: #fff transparent transparent;
}
</style>
</head>
<body>
<div class="search">
<div class="con">123</div>
<input type="text" placeholder="请输入您的快递单号" class="jd">
</div>
<script>
var con = document.querySelector('.con');
var jd_input = document.querySelector('.jd');
jd_input.addEventListener('keyup', function() {
// console.log('输入内容啦');
if (this.value == '') {
con.style.display = 'none';
} else {
con.style.display = 'block';
con.innerText = this.value;
}
})
// 当失去焦点,就隐藏这个con盒子
jd_input.addEventListener('blur', function() {
con.style.display = 'none';
})
// 获得焦点,就显示这个con盒子
jd_input.addEventListener('focus', function() {
if (this.value !== '') {
con.style.display = 'block';
}
})
</script>
</body>
</html>
BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window
Bom 由一系列相关的对象构成,并且每个对象都提供了很多方法与属性
BOM缺乏标准,JavaScript语法的标准化组织是ECMA,DOM的标准化组织是W3C,BOM最初是Netscape浏览器标准的一部分
BOM比DOM更大且包含DOM
window对象是浏览器的顶级对象,它具有双重角色
在调用的时候可以省略window,前面学习的对话框都属于window对象方法,如alert()、prompt()等
注意: window下的一个特殊属性window.name
window.onload = function() {}
或 window.addEventListener('load', function(){});
window.onload是窗口(页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS文件等),即调用处理函数
注意:
window.onload
就可以把JS代码写到页面元素的上方,因为onload是等页面内容全部加载完毕,再去执行处理函数window.onload
传统注册事件方式只能写一次,如果有多个,以最后一个window.onload
为准<!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>Document</title>
</head>
<body>
<script>
// window.onload = function() {
// var btn = document.querySelector('button');
// btn.addEventListener('click', function() {
// alert('点击我');
// })
// }
// window.onload = function() {
// alert(22);
// }
window.addEventListener('load', function() {
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
alert('点击我');
})
})
window.addEventListener('load', function() {
alert(22);
})
document.addEventListener('DOMContentLoaded', function() {
alert(33);
})
// load 等页面内容全部加载完毕,包含页面dom元素 图片 flash css等
// DOMContentLoaded DOM加载完毕,不包含图片 flash css 等就可以执行 加载速度快于load
</script>
<button>点击</button>
</body>
</html>
document.addEventListener('DOMContentLoaded', function() {})
DOMContentLoaded事件触发,仅当DOM加载完成,不包括样式表、图片和flash等
IE9以上支持
如果页面的图片很多的话,从用户访问到onload触发可能需要较长的时间,交互效果就不能实现,必然影响用户的体验,此时用DOMContentLoaded事件比较合适
window.onresize = function(){}
和 window.addEventListener('resize', function() {});
window.onresize 是调整窗口大小加载事件,当触发时就调用的处理函数
注意
<!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>Document</title>
<style>
div {
width: 200px;
height: 200px;
background: pink;
}
</style>
</head>
<body>
<script>
window.addEventListener('load', function() {
var div = document.querySelector('div');
window.addEventListener('resize', function() {
console.log('变化了');
if (window.innerWidth <= 800) {
div.style.display = 'none';
}
})
})
</script>
<div></div>
</body>
</html>
window对象提供了2个非常好用的方法-定时器
window.setTimeout(调用函数, [延迟的毫秒数]);
setTimeout()方法用于设置一个定时器,该定时器在到点儿后执行调用函数
** 注意**
<!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>Document</title>
</head>
<body>
<script>
// setTimeout 在调用时可以省略
// 延时时间单位是毫秒,但可以省略,如果省略默认为0
// 页面中可能有很多定时器,因而给定时器加标识符
setTimeout(function() {
console.log('时间到了');
}, 2000)
function callback() {
console.log('爆炸了');
}
var timer1 = setTimeout(callback, 3000);
var timer2 = setTimeout(callback, 5000);
</script>
</body>
</html>
setTimeout()这个调用函数也称为回调函数callback
普通函数是按照代码顺序直接调用,而这个函数,需要等待时间,时间到了才去调用这个函数,因此称为回调函数
<!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>Document</title>
</head>
<body>
<img src="/第三阶段/img/ad.jpg" alt="广告" class="ad">
<script>
var ad = document.querySelector('.ad');
setTimeout(function() {
ad.style.display = 'none';
}, 5000)
</script>
</body>
</html>
window.clearTimeout(timeoutID)
clearTimeout()方法取消了先前通过调用setTimeout()建立的定时器
注意
效果
<!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>Document</title>
</head>
<body>
<button>点击停止定时器</button>
<script>
var btn = document.querySelector('button');
var timer = setTimeout(function() {
alert('爆炸了');
}, 5000)
btn.addEventListener('click', function() {
clearTimeout(timer);
})
</script>
</body>
</html>
window.setInterval(回调函数,[间隔的毫秒数]);
setInterval()方法重复调用一个函数,每隔这个时间,就去调用一次回调函数
注意
<!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>Document</title>
</head>
<body>
<script>
setInterval(function() {
console.log('继续输出');
}, 1000)
// setTimeout 延时时间到了,就去调用这个回调函数,只调用一次 就结束了这个定时器
// setInterval 每隔一个延时时间,就去调用这个回调函数,会调用很多次,重复调用这个函数
</script>
</body>
</html>
案例分析
- 这个倒计时是不断变化的,因此需要定时器来自动变化(setInterval)
- 三个黑色盒子里面分别存放时分秒
- 三个黑色盒子利用innerHTML放入计算的小时分钟秒数
- 第一次执行也是间隔毫秒数,因此刚刷新页面会有空白
- 最好采取封装函数的方式,这样可以先调用一次这个函数,防止刚开始刷新页面有空白问题
应用实例
https://www.jd.com/
效果
<!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>倒计时</title>
<style>
div {
margin: 200px;
}
span {
display: inline-block;
width: 40px;
height: 40px;
background-color: #333;
font-size: 20px;
color: #fff;
text-align: center;
line-height: 40px;
}
</style>
</head>
<body>
<div>
<span class="hour">1</span>
<span class="minute">2</span>
<span class="second">3</span>
</div>
<script>
// 获取元素
var hour = document.querySelector('.hour');
var minute = document.querySelector('.minute');
var second = document.querySelector('.second');
var inputTime = +new Date('2023-3-19 18:00:00'); // 返回用户输入时间总的毫秒数
countDown();
// 开启定时器
setInterval(countDown, 1000);
function countDown() {
var nowTime = +new Date(); // 返回当前时间总的毫秒数
var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数
var h = parseInt(times / 60 / 60 % 24); // 时
h = h < 10 ? '0' + h : h;
hour.innerHTML = h;
var m = parseInt(times / 60 % 60); // 分
m = m < 10 ? '0' + m : m;
minute.innerHTML = m;
var s = parseInt(times % 60); // 当前的秒
s = s < 10 ? '0' + s : s;
second.innerHTML = s;
}
</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>Document</title>
</head>
<body>
<button class="begin">开启定时器</button>
<button class="stop">停止定时器</button>
<script>
var begin = document.querySelector('.begin');
var stop = document.querySelector('.stop');
var timer = null;
begin.addEventListener('click', function() {
timer = setInterval(function() {
console.log('ni hao ma');
}, 1000)
})
stop.addEventListener('click', function() {
clearInterval(timer);
})
</script>
</body>
</html>
案例分析
- 按钮点击之后,会禁用disabled为true
- 同时按钮里面的内容会变化,注意button里面的内容通过innerHTML修改
- 里面秒数是有变化,因此需要用到定时器
- 定义一个变量在定时器里面,不断递减
- 如果变量为0,说明到了时间,需要停止定时器且复原按钮为初始状态
效果
<!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>Document</title>
</head>
<body>
手机号码:<input type="number"> <button>发送</button>
<script>
var btn = document.querySelector('button');
var time = 5;
btn.addEventListener('click', function() {
btn.disabled = true;
var timer = setInterval(function() {
if (time == 0) {
// 清除定时器和复原按钮
clearInterval(timer);
btn.disabled = false;
btn.innerHTML = '发送';
time = 5;
} else {
btn.innerHTML = '还剩下' + time + '秒'
time--;
}
},1000)
})
</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>Document</title>
</head>
<body>
<button>点击</button>
<script>
// 全局作用域或普通函数中this指向全局对象window
console.log(this);
function fn() {
console.log(this);
}
fn();
window.setTimeout(function() {
console.log(this);
}, 1000)
// 方法调用中谁调用this就指向谁
var o = {
sayHi: function() {
console.log(this);
}
}
o.sayHi();
var btn = document.querySelector('button');
btn.onclick = function() {
console.log(this);
}
// 构造函数中this指向构造函数的实例
function Fun() {
console.log(this);
}
var fun = new Fun();
</script>
</body>
</html>
JS是单线程
JavaScript语言的一大特点就是单线程,即同一个时间只能做一件事。这是因为JavaScript这门脚本语言诞生的使命所致——JavaScript是为处理页面中用户的交互,以及操作DOM而诞生的。如对某个DOM元素进行添加和删除操作,不能同时进行,应先进行添加,之后再删除
单线程就意味着,所有任务需要排队,前一个任务结束,后一个任务才执行,这样导致的问题就是:如果JS执行时间较长,这样就会造成页面渲染不连贯又或者页面渲染加载阻塞
利用多核CPU计算能力,HTML5提出Web worker标准,允许JavaScript脚本创建多个线程,于是,JS中出现了同步和异步
同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的
异步
在做一件事情时,因为这件事情花费很长时间,在做这件事的同时,还可以去处理其他事情
本质区别:在流水线上各个流程执行顺序不同
同步任务
同步任务都在主线程上执行,形成一个执行栈
异步任务
JS的异步是通过回调函数实现的
一般而言,异步任务有以下三种类型:
异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)
JS执行机制
由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环(event loop)
window对象提供了一个location属性用于获取或设置窗体的URL,并且可以用于解析URL。因为这个属性返回的是一个对象,所以将这个属性称为location对象
统一资源定位符(Uniform Resource Locator,URL)是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,包含的信息指出文件的位置以及浏览器应该怎么处理它
URL的一般语法格式为
protocol://host[:port]/path/[?query]#fragment
实例
http://www.itcast.cn/index.html?name=andy&age=18#link
组成 | 说明 |
---|---|
protocol | 通信协议 常用的http、ftp、maito等 |
host | 主机(域名) |
port | 端口号 可选 省略时使用方案的默认端口 如http的默认端口为80 |
path | 路径 由零或多个’/'符号隔开的字符串,一般用来表示主机上的一个目录或文件地址 |
query | 参数 以键值对的形式,通过&符号分隔开来 |
fragment | 片段 #后面内容 常见于链接 锚点 |
location对象属性 | 返回值 |
---|---|
location.href | 获取或设置 整个URL |
location.host | 返回主机(域名) |
location.port | 返回端口号 如果未写返回 空字符串 |
location.pathname | 返回路径 |
location.search | 返回参数 |
location.hash | 返回片段 #后面内容 常见于链接 锚点 |
效果
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>
head>
<body>
<form action="index.html">
用户名:<input type="text" name="uname">
<input type="submit" value="登录">
form>
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>Document</title>
</head>
<body>
<div></div>
<script>
// 先去掉? substr('起始的位置', 截取几个字符)
var params = location.search.substr(1);
console.log(location.search);
// 利用=把字符串分割为数组split('=')
var arr = params.split('=');
console.log(arr[1]);
var div = document.querySelector('div');
// 把数据写入到div中
div.innerHTML = arr[1] + ' 欢迎您';
</script>
</body>
</html>
location对象方法 | 返回值 |
---|---|
location.assign() | 跟href一样,可以跳转页面(也称为重定向页面) |
location.replace() | 替换当前页面,因为不记录历史,所以不能后退页面 |
location.reload() | 重新加载页面,相当于刷新按钮或f5 如果参数为true 强制刷新 ctrl+f5 |
<!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>Document</title>
</head>
<body>
<button>点击</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click',function() {
// 记录浏览历史
// location.assign('https://www.itcast.cn');
// 不记录浏览历史
// location.replace('https://www.itcast.cn');
location.reload(true);
})
</script>
</body>
</html>
navigator对象包含有关浏览器的信息,它有很多属性,最常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值
下面前端代码可以判断用户哪个终端打开页面,实现跳转
window对象提供了一个history对象,与浏览器历史记录进行交互,该对象包含用户(在浏览器窗口中)访问过URL
history对象方法 | 作用 |
---|---|
back() | 可以后退功能 |
forward() | 前进功能 |
go(参数) | 前进后退功能 参数如果是1 前进1个页面 如果是-1 后退1个页面 |
<!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>Document</title>
</head>
<body>
<a href="Hlist.html">点击我前往列表页</a>
<button>前进</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
// history.forward();
history.go(1);
})
</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>Document</title>
</head>
<body>
<a href="Hindex.html">点击我前往首页</a>
<button>后退</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
// history.back();
history.go(-1);
})
</script>
</body>
</html>
终于学完了这部分内容,进度虽然缓慢,但还好效果还是可以的,之后就放慢看视频进度,研究研究油猴脚本书写
我知道世界是多元的,因而想用一生去证实,人间是否留有我驻足之地