admin管理员组文章数量:1588184
JavaScript-WebAPIs学习记录
浏览器交互效果
console.dir(); // 更好地查看里面的属性和方法
javascript:void(0); 或者 javascript:; 可以阻止a链接跳转
DOM
编程接口
获取元素
1、通过getElementById(‘字符串’)获取id名字,返回的是一个元素对象
2、通过getElementsByTagName(‘标签名’)获取标签名字,返回的是一个伪数组(arguments)
每个对象还是元素对象;没有元素返回任然是空的伪数组
还可以根据某个元素(父元素内部所有指定标签名子元素)
element.getElementsByTagName('标签名')
<ul id="ul">
<li>第1个</li>
<li>第2个</li>
<li>第3个</li>
<li>第4个</li>
<li>第5个</li>
</ul>
<script>
//父元素必须是单个对象(必须指明是哪个元素对象),获取的时候不包括父元素自己
// var ul = document.getElementsByTagName('ul');
// console.log(ul[0].getElementsByTagName('li'));
var ul = document.getElementById('ul');
console.log(ul.getElementsByTagName('li'));
</script>
3、通过getElementsByClassName(‘类名’)获取类名,返回一个伪数组(高版本浏览器)
4、通过document.querySelector(‘符号选择器’)根据制定选择器返回第一个对象
var boxs = document.getElementsByClassName('box');
console.log(boxs);
var box1 = document.querySelector('.box');
console.log(box1);
var nav = document.querySelector('#nav');
console.log(nav);
var li = document.querySelector('li');
console.log(li);
var boxs = document.querySelectorAll('.box');
console.log(boxs);
var lis = document.querySelectorAll('li');
console.dir(lis);
5、css属性选择器document.querySelector(‘’[属性名=属性值]‘’)
let username = document.querySelector('[name=username]') //css属性选择器:通过属性进行选择标签 【属性=值】值不需要引号 等号两边不要加空格
6、获取doby元素和html元素
//1、获取body元素
var bodyEle = document.body;
console.log(bodyEle);
console.dir(bodyEle);
//2、获取html
var htmlEle = document.documentElement;
console.log(htmlEle);
事件
1、事件源(获取元素);
2、事件类型(点击、经过;绑定事件、注册事件);
3、事件处理程序(通过匿名函数赋值;添加事件处理程序)
常见鼠标事件
操作元素
1、改变元素内容
innerText 不识别html标签、空格和换行,可读写
innerHTML识别html标签、空格和换行,可读写(W3C标准)
var btn = document.querySelector('button');
var time1 = document.querySelector('.time1');
btn.onclick = function() { //添加点击事件
//time1.innerText = '2023-4-10';
time1.innerText = getDate(); //点击显示
}
var time2 = document.querySelector('.time2'); //直接显示,不添加事件
time2.innerText = getDate();
function getDate() {
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1; //加1
var dates = date.getDate();
var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
var day = date.getDay();
return '当前日期是:' + year + '年' + month + '月' + dates + '日 ' + arr[day];
}
2、改变元素属性
操作常见属性src、href、id、alt、title等等;
操作表单元素type、value、checked、selected、disabled等等;
经常用this代替时间函数的调用者
//获取元素;
//元素.属性名 = 操作;
element.属性名 获取元素本身的属性
修改属性案例
全天问候
//全天问候
var ts = document.getElementById('ts');
var img = document.getElementsByTagName('img');
var date = new Date();
var h = date.getHours();
if(h > 6 && h < 12) {
ts.innerHTML = '上午好!';
img[0].src = './images/bg1.png';
} else if(h >= 12 && h <= 18) {
ts.innerHTML = '下午好!';
img[0].src = './images/bg2.png';
} else {
ts.innerHTML = '晚上好!';
img[0].src = './images/bg3.png';
}
密码框
<!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>
</head>
<style>
.box {
position: relative;
width: 400px;
border-bottom: 1px solid #aaa;
border-radius: 2px;
margin: 100px auto;
}
.box input {
width: 370px;
height: 30px;
border: 0;
outline: none;
}
.box img {
position: absolute;
top: 12px;
right: 2px;
width: 24px;
}
</style>
<body>
<div class="box">
<label for="">
<img src="./images/bg1.png" alt="" id="eye">
</label>
<input type="password" name="" id="pwd">
</div>
<script>
//1、获取元素
var eye = document.getElementById('eye');
var pwd = document.getElementById('pwd');
//2、注册事件,处理程序
var flag = 0; //定义flag判断是否点击
eye.onclick = function() {
//点击一次,flag变化
if(flag == 0) {
pwd.type = 'text';
eye.src = './images/bg2.png';
flag = 1; //赋值
} else {
pwd.type = 'password';
eye.src = './images/bg1.png';
flag = 0;
}
}
</script>
</body>
</html>
3、样式属性修改
element.style 行内样式修改
element.className 类名样式修改 (可以用多类名选择器,保留原来类名)
特别的:className容易覆盖以前的类名样式,我们可以通过classList方式追加和删除类名
// 追加
element.classList.add('类名');
// 删除
element.classList.remove('类名');
//切换类名,有则删除,无则添加
element.classList.toggle('类名');
// 是否包含 如果有则返回true 如果没有该类名则返回false
element.classList.contains('类名')
注意:
JS里面的样式采用的是驼峰命名法 比如 fontSize、 backgroundColor
JS修改style样式操作,产生的是行内样式,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>密码框</title>
</head>
<style>
.box {
position: relative;
width: 74px;
height: 88px;
border: 1px solid #ccc;
margin: 100px auto;
font-size: 12px;
text-align: center;
color: #f40;
}
img {
width: 60px;
margin-top: 5px;
}
.close-btn {
position: absolute;
top: -1px;
left: -16px;
width: 14px;
height: 14px;
border: 1px solid #ccc;
line-height: 14px;
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
cursor: pointer;
}
</style>
<body>
<div class="box">
CSDN
<img src="./images/CSDN.jpg" alt="">
<i class="close-btn">x</i>
</div>
<script>
//1、获取元素
var btn = document.querySelector('.close-btn');
var box = document.querySelector('.box');
//2、注册事件,处理程序
btn.onclick = function() {
box.style.display = 'none';
}
</script>
</body>
</html>
循环精灵图
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
.box {
width: 250px;
margin: 100px auto;
}
.box li {
float: left;
width: 24px;
height: 24px;
background-color: red;
margin: 15px;
background: url(./images/精灵图.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就是垂直坐标
var y = -44 * i;
lis[i].style.backgroundPosition = '0 ' + y + 'px';
}
</script>
</body>
表单隐藏文本内容
<style>
input {
color: #999;
border: 1px solid rgb(0, 35, 234);
border-radius: 2px;
}
</style>
<body>
<input type="text" value="手机">
<script>
var text = document.querySelector('input');
text.onfocus = function(){
if(this.value == '手机') {
this.value = '';
}
this.color = '#333';
}
text.onblur = function() {
if(this.value == '') {
this.value = '手机';
}
this.color = '#999';
}
</script>
</body>
密码框验证
<style>
div {
width: 600px;
margin: 100px auto;
}
.message {
display: inline-block;
font-size: 12px;
color: #999;
background: url(images/bg1.png) no-repeat left center;
background-size: 20px;
padding-left: 20px;
}
.wrong {
color: red;
background-image: url(./images/bg2.png);
}
.right {
color: green;
background-image: url(./images/bg3.png);
}
</style>
<body>
<div class="regiser">
<input type="password" class="ipt">
<p class="message">请输入6~16位密码</p>
</div>
<script>
var ipt = document.querySelector('.ipt');
var message = document.querySelector('.message');
ipt.onblur = function() {
if(this.value.length < 6 || this.value.length > 16) {
message.className = 'message wrong';
message.innerHTML = '请输入6~16位数的密码!';
} else {
message.className = 'message right';
message.innerHTML = '正确!';
}
}
</script>
</body>
排他思想
<style>
body {
background: url(./images/bg1.png) no-repeat fixed;
background-size: 100%;
background-position: center top;
/* height: 100%;
width: 100%; */
}
.box {
margin: 10px auto;
width: 120px;
}
button {
width: 10px;
height: 15px;
border-radius: 50%;
}
</style>
<body>
<div class="box">
<button></button>
<button></button>
<button></button>
</div>
<script>
var btns = document.getElementsByTagName('button'); //伪数组
for(var i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
//去掉所有按钮背景色
for(var j = 0; j < btns.length; j++) {
btns[j].style.backgroundColor = '';
}
//给点击的按钮附加背景色
this.style.backgroundColor = 'green';
}
}
</script>
</body>
图片换肤
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
body {
background: url(./images/bg1.png) fixed;
background-size: 100%;
background-position: center top;
/* height: 100%;
width: 100%; */
}
.bj {
overflow: hidden;
margin: 15px auto;
background-color: #fff;
width: 400px;
padding-top: 3px;
}
.bj li {
float: left;
margin: 0 1px;
cursor: pointer; /* 鼠标一只手 */
}
.bj img {
width: 98px;
height: 52px;
}
</style>
<body>
<ul class="bj">
<li><img src="./images/bg1.png" alt=""></li>
<li><img src="./images/bg2.png" alt=""></li>
<li><img src="./images/bg3.png" alt=""></li>
<li><img src="./images/bg4.png" alt=""></li>
</ul>
<script>
var imgs = document.querySelector('.bj').querySelectorAll('img');
for(var i = 0; i < imgs.length; i++) {
imgs[i].onclick = function() {
document.body.style.backgroundImage = 'url(' + this.src + ')';
}
}
</script>
</body>
鼠标隔行变色
<style>
table {
width: 800px;
margin: 100px auto;
text-align: center;
border-collapse: collapse;
font-size: 14px;
}
thead tr {
height: 30px;
background-color: skyblue;
}
tbody tr {
height: 30px;
}
tbody td {
border-bottom: 1px solid #d7d7d7;
font-size: 12px;
color: blue;
}
.bg {
background-color: pink;
}
</style>
<body>
<table>
<thead>
<tr>
<th>数字</th>
<th>大写字母</th>
<th>小写字母</th>
<th>字符</th>
<th>字符串</th>
<th>函数</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>A</td>
<td>a</td>
<td>'A'</td>
<td>'Aa'</td>
<td>Aa()</td>
</tr>
<tr>
<td>2</td>
<td>B</td>
<td>b</td>
<td>'B'</td>
<td>'Bb'</td>
<td>Bb()</td>
</tr>
<tr>
<td>3</td>
<td>C</td>
<td>c</td>
<td>'C'</td>
<td>'Cc'</td>
<td>Cc()</td>
</tr>
<tr>
<td>4</td>
<td>D</td>
<td>d</td>
<td>'D'</td>
<td>'Dd'</td>
<td>Dd()</td>
</tr>
<tr>
<td>5</td>
<td>E</td>
<td>e</td>
<td>'E'</td>
<td>'Ee'</td>
<td>Ee()</td>
</tr>
</tbody>
</table>
<script>
var trs = document.querySelector('tbody').querySelectorAll('tr');
//利用循环绑定事件
for(var i = 0; i < trs.length; i++) {
//鼠标经过事件 onmouseover
trs[i].onmouseover = function() {
this.className = 'bg';
}
//鼠标离开事件 onmouseout
trs[i].onmouseout = function() {
this.className = '';
}
}
</script>
</body>
全选和取消
<body>
<table>
<thead>
<tr>
<th>全选:<input type="checkbox" id="j_cbAll"></th>
<th>大写字母</th>
<th>小写字母</th>
<th>字符</th>
<th>字符串</th>
<th>函数</th>
</tr>
</thead>
<tbody id="j_tb">
<tr>
<td><input type="checkbox"></td>
<td>A</td>
<td>a</td>
<td>'A'</td>
<td>'Aa'</td>
<td>Aa()</td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>B</td>
<td>b</td>
<td>'B'</td>
<td>'Bb'</td>
<td>Bb()</td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>C</td>
<td>c</td>
<td>'C'</td>
<td>'Cc'</td>
<td>Cc()</td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>D</td>
<td>d</td>
<td>'D'</td>
<td>'Dd'</td>
<td>Dd()</td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>E</td>
<td>e</td>
<td>'E'</td>
<td>'Ee'</td>
<td>Ee()</td>
</tr>
</tbody>
</table>
<script>
//表格隔行变色
var trs = document.querySelector('tbody').querySelectorAll('tr');
//利用循环绑定事件
for(var i = 0; i < trs.length; i++) {
//鼠标经过事件 onmouseover
trs[i].onmouseover = function() {
this.className = 'bg';
}
//鼠标离开事件 onmouseout
trs[i].onmouseout = function() {
this.className = '';
}
}
//全选和取消全选
var j_cbAll = document.getElementById('j_cbAll');
var j_tbs = document.getElementById('j_tb').getElementsByTagName('input');
j_cbAll.onclick = function() {
//this.checked 得到选中状态
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 j = 0; j < j_tbs.length; j++) {
if (!j_tbs[j].checked) { //没有选中
flag = false;
//退出,提高效率;只要有一个没选中就不用继续了
break;
}
}
j_cbAll.checked = flag;
}
}
</script>
</body>
4、获取自定义元素属性
element.getAttribute(‘属性’); 主要用于获得自定义的属性;
H5新增规范和要求:以 date- 开头自定义属性 //ie11以上
//dateset是一个集合里面存放了所有以date开头的自定义属性
element.dateset.属性 //自定义有多个 - 链接属性名用驼峰命名 h5新增
element.dateset['属性'] //自定义有多个 - 链接属性名用驼峰命名比如:indexName h5新增
//可以setAttribute('属性', '要设置的属性值'); getAttribute('属性');
5、设置元素属性值
element.setAttribute(‘属性’, ‘要设置的属性值’); 主要用于设置自定义的属性
6、移除属性
element.removeAttribute(‘属性’);
tab栏切换(重要)
<style>
.tab{
width: 618px;
height: 400px;
margin: 0 auto;
}
.tab_list {
/* border-bottom: 1px solid block; */
height: 40px;
background-color: rgb(211, 208, 208);
margin: 0 auto;
}
.tab_list li {
float: left;
height: 39px;
line-height: 39px;
padding: 0 20px;
text-align: center;
cursor: pointer;
list-style: none;
}
.tab_list .current {
background-color: rgb(157, 23, 23);
color: aliceblue;
}
.tab_con{
width: 600px;
height: 75px;
margin: 0 auto;
}
.item{
height: 60px;
padding: 10px;
margin: 10px auto;
}
.item_info {
padding: 20px 0 0 20px;
}
.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>
// 1.上的模块选项卡,点击某个,当前这一个底色会是红色,其余不变(排他思想)修改类名的方式。
// 获取元素
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);
lis[i].onclick=function() {
//清楚所有current 其余的li清楚class这个类
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';
}
//留下我自己让对应的item显示出来
items[index].style.display = 'block';
}
}
</script>
</body>
节点操作
利用父子兄关系操作元素(元素、属性、文本:1、2、3)
1、父节点parentNode
最近原则,找不到为null
2、子节点childNodes
包含所有的元素节点、属性节点和文本节点,需要用循环遍历出元素节点
一般用 parent.children 获取子元素的元素节点
parent.firstChild //注意第一个可能是文本节点
parent.lastChild //注意最后一个可能是文本节点
parent.firstElementChild //返回第一个子元素节点,ie9
parent.lastElementChild //返回最后一个子元素节点,ie9
一般使用
parent.children[0]
parent.children[parent.children.length - 1]
下拉菜单
<style>
li {
list-style: none;
}
a {
text-decoration: none;
color: #000;
}
.nav {
height: 30px;
width: 322px;
background-color: #eee;
margin: 0 auto;
padding: 0;
line-height: 30px;
}
.nav li {
position: relative;
float: left;
width: 80px;
font-size: 14px;
text-align: center;
margin: 0 auto;
/* left: 50%;
transform: translate(-50%); */
background-color: #eee;
}
.nav li:hover {
background-color: #FFF5DA;
}
.nav ul {
display: none;
position: absolute;
top: 30px;
left: 0;
margin: 5px auto;
/* left: 50%;
transform: translate(-50%); */
padding: 0;
width: 100%;
border-left: 1px solid #000;
border-right: 1px solid #000;
}
.nav ul li {
margin: 0 auto;
margin-top: 4px;
border-bottom: 1px solid #000;
line-height: 20px;
text-align: center;
}
.nav ul li:hover {
background-color: #FFF5DA;
}
</style>
<body>
<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>
<li>
<a href="#">微博</a>
<ul>
<li><a href="">私信</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;
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>
3、兄弟节点nextSibling、previousSibling
nextSibling、previousSibling 包含所有元素节点、属性节点和文本节点,需要用循环遍历出元素节点(可以自己封装一个函数)
一般用 node.nextElementSibling 获取下一个兄弟元素节点 ie9
用 node.previousElementSibling 获取上一个兄弟元素节点 ie9
4、创建节点
①document.createElement(‘tagName’); 动态创建元素节点
②node.appendChild(child); 追加元素 node为父级,child为子级;
node.insertBefore(child, 指定元素) 指定元素前边添加
<body>
<ul>
<li>1111</li>
</ul>
<script>
//创建元素节点
var li = document.createElement('li');
//添加节点 node.appendChild(child); node为父级,child为子级
var ul = document.querySelector('ul');
ul.appendChild(li);
//添加元素,node.insertBefore(child, 指定元素) 指定元素前边添加
var lili = document.createElement('li');
ul.insertBefore(lili, ul.children[0]);
</script>
</body>
发布留言
<style>
textarea {
margin-left: 440px;
width: 30em;
height: 10em;
}
ul li {
width: 30em;
background-color: pink;
color: red;
font-size: 14px;
margin: 15px auto;
}
</style>
<body>
<textarea name="" id="" placeholder="请输入留言"></textarea>
<button>发布</button>
<ul>
<!-- <li>222</li> -->
</ul>
<script>
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
btn.onclick = function() {
if (text.value == '') {
alert('输入内容不能为空!')
return false;
} else {
var li = document.createElement('li');
li.innerHTML = text.value;
ul.insertBefore(li, ul.children[0]);
}
}
</script>
</body>
5、删除节点
node.removeChild(child) 删除子节点,返回删除元素
<body>
<button>删除</button>
<ul>
<li>1111</li>
<li>2222</li>
<li>3333</li>
</ul>
<script>
var btn = document.querySelector('button');
var ul = document.querySelector('ul');
btn.onclick = function() {
if (ul.children.length != 0) {
ul.removeChild(ul.children[0]);
} else {
alert('没有可删除的了!');
this.disabled = true;
return false;
}
}
</script>
</body>
发布和删除留言
<style>
textarea {
margin-left: 440px;
width: 31em;
height: 10em;
}
ul li {
width: 30em;
background-color: pink;
color: red;
font-size: 14px;
margin: 15px auto;
}
li a {
text-decoration: none;
float: right;
}
</style>
<body>
<textarea name="" id="" placeholder="请输入留言"></textarea>
<button>发布</button>
<ul>
<!-- <li>222</li> -->
</ul>
<script>
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
btn.onclick = function() {
if (text.value == '') {
alert('输入内容不能为空!')
return false;
} else {
var li = document.createElement('li');
//添加留言和删除链接
li.innerHTML = text.value + "<a href='javascript:;' >删除</a>";
ul.insertBefore(li, ul.children[0]);
//删除元素
var as = document.querySelectorAll('a');
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
//node.removeChild(child) 要删除li是当前a的父元素 this.parentNode
ul.removeChild(this.parentNode);
}
}
}
}
</script>
</body>
6、复制节点
①node.cloneNode() 复制;参数为空或者false,浅拷贝,只复制标签不复制内容;可以添加true,深复制
②node.appendChild(child); 追加元素 node为父级,child为子级;
node.insertBefore(child, 指定元素) 指定元素前边添加
动态生成表格
<!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>
a {
text-decoration: none;
color: red;
padding: 0 2px;
border: 1px solid black;
border-radius: 2px;
}
table {
width: 500px;
margin: 100px auto;
border-collapse: center;
}
td,
th {
border: 1px solid #333;
text-align: center;
}
thead tr {
height: 40px;
background-color: #ccc;
}
tbody tr {
height: 30px;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script>
//1、准备数据
var dates = [{
name: '张三',
subject: 'JavaScript',
score: 98
},{
name: '李四',
subject: 'JavaScript',
score: 89
},{
name: '王五',
subject: 'JavaScript',
score: 71
},{
name: '赵六',
subject: 'JavaScript',
score: 65
}];
//2、向tbody里面创建行,行数等于数组长度
var tbody = document.querySelector('tbody');
for (var i = 0; i < dates.length; i++) {
//创建tr
var tr = document.createElement('tr');
tbody.appendChild(tr);
for (var k in dates[i]) { // 里面的for循环 列数 td
//创建单元格td
var td = document.createElement('td');
//赋值
td.innerHTML = dates[i][k];
tr.appendChild(td);
}
// 3、创建有删除2个字的单元格
var td = document.createElement('td');
td.innerHTML = '<a href="javascript:;">删除</a>';
tr.appendChild(td);
}
//4、删除操作
var as = document.querySelectorAll('a');
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
alert('确定要删除吗?三思!')
//点击a删除所在行, "a.td.tr" node.removeChild(child);
tbody.removeChild(this.parentNode.parentNode);
}
}
</script>
</body>
</html>
7、三种动态创建元素
①document.write(); 创建元素,如果页面文档流加载完毕,再调用这句话会导致重绘
像是点击创建
window.onload = funcion(){
document.write('<div>123</div>');
}
②innerHTML 拼接字符串效率低,如果采取数组模式 [join(‘’)逗号分隔] 效率更高
③document.createElement(‘tagName’); 结构清晰
8、重绘和回流
重绘
简单来说就是重新绘画,当给一个元素更换颜色、更换背景,虽然不会影响页面布局,但是颜色或背景变了,就会重新渲染页面,这就是重绘。
回流
当增加或删除dom节点,或者给元素修改宽高时,会改变页面布局,那么就会重新构造dom树然后再次进行渲染,这就是回流。
总结
重绘不会引起dom结构和页面布局的变化,只是样式的变化,有重绘不一定有回流。
回流则是会引起dom结构和页面布局的变化,有回流就一定有重绘。
不管怎么说都是会影响性能。
怎么进行优化或减少?
1.多个属性尽量使用简写,例如:boder可以代替boder-width、boder-color、boder-style
2.创建多个dom节点时,使用documentfragment创建
3.避免使用table布局
4.避免设置多层内联样式,避免节点层级过多
5.避免使用css表达式
6.将频繁重绘或回流的节点设置为图层,图层能够阻止该节点的渲染行为影响到别的节点(例:will-change\video\iframe等标签),浏览器会自动将该节点变为图层
事件高级
注册事件
1、传统注册方式以on开头的事件具有唯一性,会覆盖之前的;
2、方法监听注册事件,同一个元素同一个事件可以注册多个监听器,按注册顺序执行
w3c标准,addEventListener()它是一个方法,ie9之前可以用attachEvent代替
eventTarget.addEventListener(type, listener[, userCapture]);
//type是字符串需要加'',不用添加on
//listener不需要添加(),直接写函数名
//userCapture可有可无,默认为false
eventTarget.attachEvent(eventNameWithOn, callback) //ie9以前,独有
//eventNameWithOn 带on的事件字符串
//callback 事件处理函数
3、封装
删除事件
1、传统解绑 eventTarget.οnclick=null;
2、方法监听注册方式
eventTarget.removeEventListener(type, listener[, userCapture]);
eventTarget.detachEvent(eventNameWithOn, callback);
3、封装
事件流
事件发生的传播过程
事件捕获–>处于目标阶段–>冒泡阶段
eventTarget.removeEventListener(type, listener[, userCapture]);
如果 userCapture为ture ,则处于捕获阶段;如果为false或者为空,为冒泡阶段
注意:
事件对象
eventTarget.onclick = function(event) {};
eventTarget.removeEventListener(type, function(event) {});
1、event 就是事件对象监听函数小括号内,当形参来看,不需要传实参去
2、事件对象必须有了事件才会存在,系统自建
3、事件对象里面有相关属性方法
4、事件对象我们可以自己命名 e等
5、有兼容性问题 ie678 通过 window.event 兼容性写法: e = e || window.event;
6、e.target (ie9以上有效,之前的用e.srcElement)返回的是触发事件对象(点击哪个就返回那个),this (currentTarget有兼容性问题)返回绑定事件方法
7、e.preventDefault(); 阻止默认行为(事件)|| e.returnValue; || return false;(后边代码不执行,只限于传统注册方式)
阻止事件冒泡
e.stopPropagation(); //阻止传播 ie678用:window.event.cancelBubble = ture;
e.preventDefault();阻止默认行为
<script>
//禁用鼠标右键菜单
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
});
//禁用鼠标选中
document.addEventListener('selectstart', function(e) {
e.preventDefault();
});
</script>
事件委托
不是每个子节点单独设置事件监听器,而是时间监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点
可以与e.target配合使用
鼠标事件对象和键盘事件对象
1、常用鼠标事件对象
鼠标位置图片
<style>
img {
position: absolute;
width: 40px;
}
</style>
</head>
<body>
<img src="images/angle2.gif" alt="">
<script>
var angle = document.querySelector('img');
document.addEventListener('mousemove', function(e) {
var x = e.pageX;
var y = e.pageY;
angle.style.left = x - 20 + 'px';
angle.style.top = y - 20 + 'px';
})
</script>
</body>
2、常见键盘事件
键盘事件 | 触发事件 |
---|---|
onkeyup | 某个按钮按键被松开时触发 |
onkeydown | 某个按钮按键被按下时触发 |
onkeypress | 某个按钮按键被按下时触发 但是他不识别功能键 比如 ctrl shif 箭头等 |
先执行onkeydown,再执行onkeypress,最后执行onkeyup;记得事件监听没有on
keydown、keyup 不区分大小写,A和a的e.keyCode返回值ASCII都是65;
keypress 区分大小写,A和a的e.keyCode返回值ASCII分别是65和97;
<style>
.father {
margin: 100px auto;
position: relative;
width: 178px;
height: 150px;
}
.big {
position: absolute;
display: none;
top: -40px;
width: 171px;
border: 1px solid rgb(0, 0, 0, 0.2);
box-shadow: 0 2px 4px rgb(0, 0, 0, 0.2);
padding: 5px 0;
font-size: 20px;
line-height: 20px;
color: #333;
}
.big::before {
content: '';
width: 0;
height: 0;
position: absolute;
top: 28px;
left: 18px;
border: 8px solid; /* 盒子边框尺寸要等于一半盒子高度 */
border-color: #fff transparent transparent; /* 颜色要设置为透明transparent */
}
</style>
</head>
<body>
<div class="father">
<div class="big">123</div>
<input type="text" placeholder="请输入..." class="son">
</div>
<script>
var big = document.querySelector('.big');
var search = document.querySelector('input');
document.addEventListener('keyup', function(e) {
console.log(e.keyCode);
if (e.keyCode === 83) {
search.focus();
}
});
//此处不能用keydown、keypress
search.addEventListener('keyup', function () {
if (this.value == '') {
big.style.display = 'none';
} else {
big.style.display = 'block';
big.innerHTML = this.value;
}
})
</script>
</body>
注意:keydown和keypress在文本框内特点,就是他们触发的时候,文字还没有落入文本框内
BOM
浏览器对象模型
window对象常见事件
1、窗口加载事件
文档内容加载完毕才会触发
window.onload = function(){}
或者
window.addEventListener('load', function(){})
window.onload 传统的方式只能写一次,多个以后者为准
addEventListioner('DOMContentLoaded',function(){})
DOM加载完毕,不包括图片 fash css等就可以执行,速度比load快
2、调整窗口大小事件
window.onresize = function() {};
winow.addEventListioner('resize', function(){});
经常利用它完成响应式布局,window.innerWidth当前屏幕宽度
3、定时器
①隔了多少时间调用(回调函数)
window.setTimeout(function(){}, 延时时间(毫秒))
window可以省略;
可以直接写函数 ,或者 写函数名 或者 采用字符串 ‘ 函数名()’三种格式;
毫秒默认是0,写的话必须是毫秒数
可以给他赋值一个标识符
还可以通过递归函数实现定时器的功能
<div></div>
<script>
let div = document.querySelector('div')
function fn() {
div.innerHTML = new Date().toLocaleString()
setTimeout(fn, 1000)
}
fn()
</script>
②停止setTimeout() 定时器
window.clearTimeout(timeoutID);
③setInterval()定时器,每隔一段时间就调用一次
window.setInterval(回调函数, [间隔毫秒数]);
window可以省略;
可以**直接写函数 **,或者 写函数名 或者 采用字符串‘函数名()’三种格式;
毫秒默认是0,写的话必须是毫秒数
可以给他赋值一个标识符
案例
倒计时
<style>
span {
display: inline-flex;
width: 20px;
height: 20px;
margin: 10px auto;
padding: 10px;
background-color: black;
color: aliceblue;
}
</style>
<script>
window.addEventListener('load', function(){
var hour = document.querySelector('.hour');
var minute = document.querySelector('.minute');
var second = document.querySelector('.second');
var inputTime = +new Date('2023-4-21 18:00:00'); //用户输入时间的总毫秒数
countDown(); // 先调用一次,防止第一次刷新空白
//开启定时器
setInterval(countDown, 1000);
// 转化公式如下:
// h = parseInt(总秒数 / 60 / 60); //计算小时,注意不用%24求余,因为没有天数
// m = parseInt(总秒数 / 60 % 60); //计算分数
// s = parseInt(总秒数 % 60); //计算当前秒数
function countDown() {
var nowTime = +new Date(); //当前时间的总毫秒数
var times = (inputTime - nowTime) / 1000; //剩余时间总秒数
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>
</head>
<body>
<span class="hour"></span>
<span class="minute"></span>
<span class="second"></span>
</body>
开启停止定时器
<title>开启停止定时器</title>
<script>
window.addEventListener('load', function() {
var begin = document.querySelector('.begin');
var stop = document.querySelector('.stop');
var times = null; //全局变量,null一个空对象
begin.addEventListener('click', function() {
times = setInterval(function() {
console.log('你好吗!');
}, 1000)
})
stop.addEventListener('click', function() {
clearTimeout(times);
})
})
</script>
</head>
<body>
<button class="begin">开启定时器</button>
<button class="stop">停止定时器</button>
</body>
发送3秒计时器
<script>
window.addEventListener('load', function() {
var btn = document.querySelector('button');
var time = 3; //定义剩下秒数
btn.addEventListener('click', function() {
//禁用按钮
this.disabled = true;
//定义定时器
var timer = setInterval(function() {
if (time == 0) {
//时间到了,清楚定时器复原按钮和时间
clearInterval(timer);
btn.disabled = false;
btn.innerHTML = '发送';
time = 3; //重新开始
} else {
btn.innerHTML = time + '秒';
time--;
}
}, 1000)
})
})
</script>
this
指向父元素
同步、异步(面试)
事件循环(event loop)
location对象
location.reload 刷新
点击10秒后跳转
<button>点击</button>
<div></div>
<script>
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.addEventListener('click', function() {
time = 10;
setInterval(function() {
if (time == 0) {
location.href = 'http://www.baidu';
time = 10;
} else {
div.innerHTML = '你将在' + time + '秒钟后跳转到页面';
time--;
}
}, 1000)
})
</script>
表单提交欢迎
登录页面
<form action="index.html">
用户名:<input type="text" name="uname">
<input type="submit" value="登录">
</form>
首页
<div></div>
<script>
console.log(location.search); // ?uname=ssy
//1、截取字符,substa('起始位置',截取几个字符)
var params = location.search.substr(1); //默认截取后边全部
console.log(params); // uname=ssy
//2、分隔,split('分隔符'),分割为数组
var str = params.split('=');
console.log(str); // ['uname','ssy']
//3、调用
var div = document.querySelector('div');
div.innerHTML = str[1] + '欢迎你!';
</script>
location 对象方法
navigator对象
它包含浏览器相关信息
常用userAgent属性检查浏览器版本及平台
history对象
PC端网页特效
元素偏移量offset系列
1、offset概述
2、offset与style区别
案例
鼠标在盒子中的坐标
<style>
* {
margin: 0;
padding: 0;
}
.box {
position: relative;
margin: 200px;
width: 400px;
height: 400px;
background-color: rgb(54, 219, 134);
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var box = document.querySelector('.box');
box.addEventListener('mousemove', function(e){
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
this.innerHTML = 'x坐标是:' + x + ',y坐标是:' + y;
})
</script>
</body>
模态框拖拽
<style>
* {
padding: 0px;
margin: 0px;
}
.login-header {
width: 100%;
text-align: center;
height: 30px;
font-size: 24px;
line-height: 30px;
}
.login {
display: none;
width: 512px;
height: 280px;
position: fixed;
border: #ebebeb solid 1px;
left: 50%;
top: 50%;
background: #ffffff;
box-shadow: 0px 0px 20px #ddd;
z-index: 9999;
transform: translate(-50%, -50%);
}
.login-title {
width: 100%;
margin: 10px 0px 0px 0px;
text-align: center;
line-height: 40px;
height: 40px;
font-size: 18px;
position: relative;
cursor: move;
}
.login-input-content {
margin-top: 20px;
}
.login-button {
width: 50%;
margin: 30px auto 0px auto;
line-height: 40px;
font-size: 14px;
border: #ebebeb 1px solid;
text-align: center;
}
.login-bg {
display: none;
width: 100%;
height: 100%;
position: fixed;
top: 0px;
left: 0px;
background: rgba(0, 0, 0, .3);
}
a {
text-decoration: none;
color: #000000;
}
.login-button a {
display: block;
}
.login-input input.list-input {
float: left;
line-height: 35px;
height: 35px;
width: 350px;
border: #ebebeb 1px solid;
text-indent: 5px;
}
.login-input {
overflow: hidden;
margin: 0px 0px 20px 0px;
}
.login-input label {
float: left;
width: 90px;
padding-right: 10px;
text-align: right;
line-height: 35px;
height: 35px;
font-size: 14px;
}
.login-title span {
position: absolute;
font-size: 12px;
right: -20px;
top: -30px;
background: #ffffff;
border: #ebebeb solid 1px;
width: 40px;
height: 40px;
border-radius: 20px;
}
</style>
</head>
<body>
<div class="login-header"><a id="link" href="javascript:;">点击,弹出登录框</a></div>
<!-- 弹出框 -->
<div id="login" class="login">
<div id="title" class="login-title">登录会员
<span><a id="closeBtn" href="javascript:void(0);" class="close-login">关闭</a></span>
</div>
<div class="login-input-content">
<div class="login-input">
<label>用户名:</label>
<input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
</div>
<div class="login-input">
<label>登录密码:</label>
<input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input">
</div>
</div>
<div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登录会员</a></div>
</div>
<!-- 遮盖层 -->
<div id="bg" class="login-bg"></div>
<script>
// 1. 获取元素
var login = document.querySelector('.login');
var mask = document.querySelector('.login-bg');
var link = document.querySelector('#link');
var closeBtn = document.querySelector('#closeBtn');
var title = document.querySelector('#title');
// 2. 点击弹出层这个链接 link 让mask 和login 显示出来
link.addEventListener('click', function() {
mask.style.display = 'block';
login.style.display = 'block';
})
// 3. 点击 closeBtn 就隐藏 mask 和 login
closeBtn.addEventListener('click', function() {
mask.style.display = 'none';
login.style.display = 'none';
})
// 4. 开始拖拽
// (1) 当我们鼠标按下, 就获得鼠标在盒子内的坐标
title.addEventListener('mousedown', function(e) {
var x = e.pageX - login.offsetLeft;
var y = e.pageY - login.offsetTop;
// (2) 鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top值
document.addEventListener('mousemove', move)
function move(e) {
login.style.left = e.pageX - x + 'px';
login.style.top = e.pageY - y + 'px';
}
// (3) 鼠标弹起,就让鼠标移动事件移除
document.addEventListener('mouseup', function() {
document.removeEventListener('mousemove', move);
})
})
</script>
</body>
放大镜
//css
.preview_img {
position: relative;
height: 398px;
border: 1px solid #ccc;
}
.preview_img>img {
width: 400px;
}
.mask {
display: none;
position: absolute;
top: 0;
left: 0;
width: 300px;
height: 300px;
background: #FEDE4F;
opacity: .5;
border: 1px solid #ccc;
cursor: move;
}
.big {
display: none;
position: absolute;
left: 410px;
top: 0;
width: 500px;
height: 500px;
background-color: pink;
z-index: 999;
border: 1px solid #ccc;
overflow: hidden;
}
.big img {
position: absolute;
top: 0;
left: 0;
}
//body
<div class="preview_img">
<img src="images/sj3.png" alt="" >
<div class="mask"></div>
<div class="big">
<img src="images/sj3.png" alt="" class="bigImg">
</div>
</div>
//js
/* detail.js */
window.addEventListener('load', function() {
var preview_img = document.querySelector('.preview_img');
var mask = document.querySelector('.mask');
var big = document.querySelector('.big');
// 1. 当我们鼠标经过 preview_img 就显示和隐藏 mask 遮挡层 和 big 大盒子
preview_img.addEventListener('mouseover', function() {
mask.style.display = 'block';
big.style.display = 'block';
})
preview_img.addEventListener('mouseout', function() {
mask.style.display = 'none';
big.style.display = 'none';
})
// 2. 鼠标移动的时候,让黄色的盒子跟着鼠标来走
preview_img.addEventListener('mousemove', function(e) {
// (1). 先计算出鼠标在盒子内的坐标
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
// console.log(x, y);
// (2) 减去盒子高度 300的一半 是 150 就是我们mask 的最终 left 和top值了
// (3) 我们mask 移动的距离
var maskX = x - mask.offsetWidth / 2;
var maskY = y - mask.offsetHeight / 2;
// (4) 如果x 坐标小于了0 就让他停在0 的位置
// 遮挡层的最大移动距离
var maskMax = preview_img.offsetWidth - mask.offsetWidth;
if (maskX <= 0) {
maskX = 0;
} else if (maskX >= maskMax) {
maskX = maskMax;
}
if (maskY <= 0) {
maskY = 0;
} else if (maskY >= maskMax) {
maskY = maskMax;
}
mask.style.left = maskX + 'px';
mask.style.top = maskY + 'px';
// 3. 大图片的移动距离 = 遮挡层移动距离 * 大图片最大移动距离 / 遮挡层的最大移动距离
// 大图
var bigIMg = document.querySelector('.bigImg');
// 大图片最大移动距离
var bigMax = bigIMg.offsetWidth - big.offsetWidth;
// 大图片的移动距离 X Y
var bigX = maskX * bigMax / maskMax;
var bigY = maskY * bigMax / maskMax;
bigIMg.style.left = -bigX + 'px';
bigIMg.style.top = -bigY + 'px';
})
})
元素可视区client系列
区别注意
offsetX和offsetY
offsetX:鼠标点击位置相对于触发事件对象的水平距离
offsetY:鼠标点击位置相对于触发事件对象的垂直距离
clientX和clientY
clientX:鼠标点击位置相对于浏览器可视区的水平距离(不会计算水平滚动的距离)
clientY:鼠标点击位置相对于浏览器可视区的垂直距离(不会计算垂直滚动条的距离)
screenX 和screenY
screenX和screenY
screenX:鼠标点击位置相对于电脑屏幕左上角的水平距离
screenY:鼠标点击位置相对于电脑屏幕左上角的垂直距离
pageX和pageY
pageX:clientX+X1(X1为水平滚动的距离)
pageY:clientY+Y1(Y1为垂直滚动的距离)
特别的
window.pageYOffset 返回页面被卷去的头部距离
window.pageXOffset 返回页面被卷去的左侧距离
立即执行函数
立即执行函数 ( function(){} ) ( ) 或者 ( function(){}() )
主要作用:
创建一个独立的作用域。 避免了命名冲突问题
代码演示:
<script>
// 1.立即执行函数: 不需要调用,立马能够自己执行的函数
function fn() {
console.log(1);
}
fn();
// 2. 写法 也可以传递参数进来
// 1.(function() {})() 或者 2. (function(){}());
(function(a, b) {
console.log(a + b);
var num = 10;
})(1, 2); // 第二个小括号可以看做是调用函数
(function sum(a, b) {
console.log(a + b);
var num = 10; // 局部变量
}(2, 3));
// 3. 立即执行函数最大的作用就是 独立创建了一个作用域, 里面所有的变量都是局部变量 不会有命名冲突的情况
</script>
淘宝 flexible.js 源码分析
(function flexible(window, document) {
// 获取的html 的根元素
var docEl = document.documentElement
// dpr 物理像素比
var dpr = window.devicePixelRatio || 1
// adjust body font size 设置我们body 的字体大小
function setBodyFontSize() {
// 如果页面中有body 这个元素 就设置body的字体大小
if (document.body) {
document.body.style.fontSize = (12 * dpr) + 'px'
} else {
// 如果页面中没有body 这个元素,则等着 我们页面主要的DOM元素加载完毕再去设置body
// 的字体大小
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
// set 1rem = viewWidth / 10 设置我们html 元素的文字大小
function setRemUnit() {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize 当我们页面尺寸大小发生变化的时候,要重新设置下rem 的大小
window.addEventListener('resize', setRemUnit)
// pageshow 是我们重新加载页面触发的事件
window.addEventListener('pageshow', function(e) {
// e.persisted 返回的是true 就是说如果这个页面是从缓存取过来的页面,也需要从新计算一下rem 的大小
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports 有些移动端的浏览器不支持0.5像素的写法
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
}(window, document))
元素滚动scroll系列
1、scroll 概述
scroll 翻译过来就是滚动的,我们使用 scroll 系列的相关属性可以动态的得到该元素的大小、滚动距离等。
scroll案例 | 作用 |
---|---|
element.scrollTop | 返回被卷去的上侧距离,返回数值不带单位,可读写 |
element.scrollLeft | 返回被卷去的左侧距离,返回数值不带单位 |
element.scrollWidth | 返回自身实际的宽度,不含边框,返回数值不带单位 |
element.scrollHeight | 返回自身实际的高度,不含边框,返回数值不带单位 |
页面被卷去的头部:
如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll事件。
2、案例
scroll案例
<title>scroll案例</title>
<style>
.slider-bar {
position: absolute;
left: 50%;
top: 300px;
margin-left: 600px;
width: 45px;
height: 130px;
background-color: rgb(47, 36, 168);
}
a {
text-decoration: none;
color: rgb(136, 13, 13);
}
.w {
width: 1200px;
margin: 10px auto;
}
.header {
height: 150px;
background-color: rgb(120, 11, 27);
}
.banner {
height: 250px;
background-color: rgb(238, 206, 46);
}
.main {
height: 1000px;
background-color: yellowgreen;
}
span {
display: none;
position: absolute;
bottom: 0;
}
</style>
</head>
<body>
<div class="slider-bar">
<span class="goBack">
<a href="#">返回顶部</a>
</span>
</div>
<div class="header w">头部区域</div>
<div class="banner w">banner区域</div>
<div class="main w">主体部分</div>
<script>
//1. 获取元素
var sliderbar = document.querySelector('.slider-bar');
var banner = document.querySelector('.banner');
// banner.offestTop 就是被卷去头部的大小 一定要写到滚动的外面
var bannerTop = banner.offsetTop;
// 当我们侧边栏固定定位之后应该变化的数值
var sliderbarTop = sliderbar.offsetTop - bannerTop;
// 获取main 主体元素
var main = document.querySelector('.main');
var goBack = document.querySelector('.goBack');
var mainTop = main.offsetTop;
// 2. 页面滚动事件 scroll
document.addEventListener('scroll', function() {
// console.log(11);
// window.pageYOffset 页面被卷去的头部
// console.log(window.pageYOffset);
// 3 .当我们页面被卷去的头部大于等于了 172 此时 侧边栏就要改为固定定位
if (window.pageYOffset >= bannerTop) {
sliderbar.style.position = 'fixed';
sliderbar.style.top = sliderbarTop + 'px';
} else {
sliderbar.style.position = 'absolute';
sliderbar.style.top = '300px';
}
// 4. 当我们页面滚动到main盒子,就显示 goback模块
if (window.pageYOffset >= mainTop) {
goBack.style.display = 'block';
} else {
goBack.style.display = 'none';
}
})
</script>
</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>电梯导航</title>
<style>
* {
margin: 0;
padding: 0;
}
.aside {
position: fixed;
margin: 140px 10px;
width: 80px;
}
.aside .aside1, .aside .aside2, .aside .aside3, .aside .aside4 {
width: 80px;
float: left;
text-align: center;
line-height: 40px;
transition: all 100ms;
cursor: pointer;
}
.active {
background-color: red;
}
.content {
margin: 100px auto;
width: 800px;
height: 2300px;
}
.content .content1, .content .content2, .content .content3, .content .content4 {
float: left;
width: 800px;
height: 500px;
font-size: 20px;
text-align: center;
line-height: 500px;
color: #fcfc10;
}
.content1 {
background-color: red;
}
.content2 {
background-color: green;
}
.content3 {
background-color: blue;
}
.content4 {
background-color: black;
}
</style>
</head>
<body>
<div class="box">
<div class="aside">
<div class="aside1 active">小红</div>
<div class="aside2">小绿</div>
<div class="aside3">小蓝</div>
<div class="aside4">小黑</div>
</div>
<div class="content">
<div class="content1">小红的内容</div>
<div class="content2">小绿的内容</div>
<div class="content3">小蓝的内容</div>
<div class="content4">小黑的内容</div>
</div>
</div>
<script>
let aside = document.querySelector('.aside')
let asides = aside.children
let content = document.querySelector('.content')
let contents = content.children
for (let i = 0; i < asides.length; i++) {
asides[i].addEventListener('click', function() {
// 或者使用排他思想
// for (let i = 0; i < asides.length; i++) {
// asides[i].classList.remove('active')
// }
document.querySelector('.aside .active').classList.remove('active')
this.classList.add('active')
// 内容盒子移动,页面滚动
document.documentElement.scrollTop = contents[i].offsetTop
})
}
</script>
</body>
</html>
页面被卷去的头部兼容性解决方案
需要注意的是,页面被卷去的头部,有兼容性问题,因此被卷去的头部通常有如下几种写法:
- 声明了 DTD,使用 document.documentElement.scrollTop
- 未声明 DTD,使用 document.body.scrollTop
- 新方法 window.pageYOffset和 window.pageXOffset,IE9 开始支持
function getScroll() {
return {
left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft||0,
top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
};
}
getScroll().left
三大系列总结
三大系列比较 | 作用 |
---|---|
e.offsetWidthh | 返回自身包括padding、边框、内容区的宽度, 返回数值不带单位 |
e.clientWidth | 返回自身包括padding、内容区域宽度,不含边框,不带单位 |
e.scrollWidth | 返回自身实际宽度,不含边框,不带单位 |
常见用法:
- offset经常用于获取元素位置:offsetLeft offsetTop
- client经常用于获取元素大小,clientWidth clientHeight
- scroll经常用于获取滚动距离scrollTop scrollLeft
- 注意页面滚动距离通过window.pageYOffset获取
mouseenter和mouseover的区别
1、mouseenter和mouseleave
- 当鼠标移动到元素上时就会触发mouseenter 事件,mouseenter 只会经过自身盒子触发
- mouseenter不会冒泡
- 跟mouseenter搭配鼠标离开 mouseleave 同样不会冒泡
2、mouseover和mouseout
- mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发
- mouseover会冒泡
动画函数封装
1、动画实现原理
核心原理:通过定时器setInterval()不断移动盒子的位置
实现步骤
1、获得盒子当前的位置
2、让盒子在当前位置加上移动的距离(步长)
3、注意元素需要添加定位,才能使用element.style.left
4、利用定时器不断重复这个操作
5、加上一个结束定时器的条件
停止的条件:让当前盒子的位置等于目标位置就停止定时器(实质是删除定时器)
6、回调函数写的位置:定时器结束的位置,当动画执行结束后才去调用该该函数
案例
<!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 {
position: absolute;
width: 100px;
height: 100px;
background-color: #965b5b;
}
span {
position: absolute;
left: 0;
top: 200px;
width: 200px;
height: 200px;
background-color: #0ee978;
}
</style>
</head>
<body>
<button>点击小绿才走</button>
<div></div>
<span>小绿</span>
<script>
//动画原理函数封装
//性能优化,利用对象给不同的元素添加不同的定时器
function animate(obj,target) {
// 不断点击按钮,动画效果会越来越快,因为开启太多定时器了
// 解决方案,让元素只有一个定时器执行
// 清楚以前的定时器,只保留当前的
clearInterval(obj.timer);
obj.timer = setInterval(function() {
if(obj.offsetLeft >= target) {
// 停止动画定时器
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
},30);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
var btn = document.querySelector('button');
animate(div, 500);
btn.addEventListener('click', function() {
animate(span, 200);
})
</script>
</body>
</html>
2、缓动效果原理
缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来。
思路:
①让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
②核心算法:(目标值-现在的位置)/ 10 作为每次移动的距离
③停止的条件是:让当前盒子位置等于目标位置就停止定时器
案例
<!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>
span {
position: absolute;
left: 0;
top: 200px;
width: 200px;
height: 200px;
background-color: #0ee978;
}
</style>
</head>
<body>
<button class="btn500">点击小绿走到500</button>
<button class="btn1000">点击小绿走到1000</button>
<span>小绿</span>
<script>
//动画原理函数封装
//性能优化,利用对象给不同的元素添加不同的定时器
function animate(obj,target) {
// 不断点击按钮,动画效果会越来越快,因为开启太多定时器了
// 解决方案,让元素只有一个定时器执行
// 清楚以前的定时器,只保留当前的
clearInterval(obj.timer);
obj.timer = setInterval(function() {
//步长公式
// 把步长值改为整数,避免小数问题
// var step = Math.ceil((target - obj.offsetLeft) / 10); //进一法,向上取整
var step = (target - obj.offsetLeft) / 10;
// 判断步长是否大于0,小于0向下取整
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if(obj.offsetLeft == target) {
// 停止动画定时器
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + step + 'px';
},15);
}
var span = document.querySelector('span');
var btn500 = document.querySelector('.btn500');
var btn1000 = document.querySelector('.btn1000');
btn500.addEventListener('click', function() {
animate(span, 500);
});
btn1000.addEventListener('click', function() {
animate(span, 1000);
})
</script>
</body>
</html>
3、动画函数添加回调函数
回调函数原理:函数可以作为一个参数,将这个函数作为一个参数传导另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调
案例
<!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>
span {
position: absolute;
left: 0;
top: 200px;
width: 200px;
height: 200px;
background-color: #0ee978;
}
</style>
</head>
<body>
<button class="btn500">点击小绿走到500</button>
<button class="btn1000">点击小绿走到1000</button>
<span>小绿</span>
<script>
//动画原理函数封装
//性能优化,利用对象给不同的元素添加不同的定时器
function animate(obj, target, callback) {
// 不断点击按钮,动画效果会越来越快,因为开启太多定时器了
// 解决方案,让元素只有一个定时器执行
// 清楚以前的定时器,只保留当前的
clearInterval(obj.timer);
obj.timer = setInterval(function() {
//步长公式
// 把步长值改为整数,避免小数问题
// var step = Math.ceil((target - obj.offsetLeft) / 10); //进一法,向上取整
var step = (target - obj.offsetLeft) / 10;
// 判断步长是否大于0,小于0向下取整
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if(obj.offsetLeft == target) {
// 停止动画定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束位置
if (callback) {
// 调用函数
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px';
},15);
}
var span = document.querySelector('span');
var btn500 = document.querySelector('.btn500');
var btn1000 = document.querySelector('.btn1000');
btn500.addEventListener('click', function() {
animate(span, 500);
});
btn1000.addEventListener('click', function() {
animate(span, 1000, function() {
span.style.backgroundColor = 'red';
});
})
</script>
</body>
</html>
4、动画函数封装到单独js文件
动画函数的使用较为频繁,将其封装到一个独立js文件需要时直接引用
<script>
var sliderbar = document.querySelector('.sliderbar');
var con = document.querySelector('.con');
var span = document.querySelector('span');
var conLeft = con.offsetLeft;
span.addEventListener('mouseenter', function () {
animate(con, con.offsetLeft - con.offsetWidth, function () {
sliderbar.children[0].innerHTML = '→';
});
})
span.addEventListener('mouseout', function() {
animate(con, conLeft, function () {
sliderbar.children[0].innerHTML = '←';
});
})
</script>
5、节流阀
防止轮播图按钮连续点击造成播放过快。
节流阀目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发,跳转过快。
核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数
开始设置一个变量var flag = true;
if(flag) {flag = false; do something} 关闭水龙头
利用回调函数 动画执行完毕, flag = true 打开水龙头
6、案例
轮播图
<!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>
.lunbo li a img{
width: 850px;
height: 450px;
}
.lunbo li{
float: left;
}
.lunbo{
position: absolute;
top: 0;
left: 0;
margin: 0;
padding: 0;
width: 600%;
/* 父盒子比ul小,一行显示不完,所以不能浮动,必须设置ul的宽度足够宽 */
}
.focus{
position: relative;
width: 850px;
height: 450px;
background-color: purple;
margin: 100px auto;
overflow: hidden;
}
.arrow-l,.arrow-r{
display: none;
position: absolute;
top: 50%;
margin-top: -20px;
width: 24px;
height: 40px;
background: rgba(0, 0, 0, .3);
text-align: center;
text-decoration: none;
line-height: 40px;
color: #fff;
font-family: 'icomoon';
font-size: 18px;
z-index: 2;
}
.arrow-r{
right: 0;
}
.circle li{
float: left;
width: 8px;
height: 8px;
border: 2px solid rgba(255, 255, 255, 0.5);
border-radius: 50%;
margin: 0 3px;
cursor: pointer;
}
.circle{
position: absolute;
bottom: 10px;
left: 300px;
}
.focus img{
width: 850px;
height: 450px;
}
ul li{
list-style: none;
}
.current{
background-color: #fff;
}
</style>
</head>
<script src="js/JS.js"></script>
<body>
<div class="focus f1">
<!-- 左侧按钮 -->
<a href="javascript:;" class="arrow-l"><</a>
<!-- 右侧按钮 -->
<a href="javascript:;" class="arrow-r">></a>
<!-- 核心滚动区域 -->
<ul class="lunbo">
<li>
<a href="#"><img src="./images/bg1.png" alt="" class="image"></a>
</li>
<li>
<a href="#"><img src="./images/bg2.png" alt=""></a>
</li>
<li>
<a href="#"><img src="./images/bg3.png" alt=""></a>
</li>
<li>
<a href="#"><img src="./images/bg4.png" alt=""></a>
</li>
</ul>
<!-- 下面的小圆圈 -->
<ul class="circle">
</ul>
</div>
</body>
</html>
window.onload = function() {
//性能优化,利用对象给不同的元素添加不同的定时器
function animate(obj, target, callback) {
// 不断点击按钮,动画效果会越来越快,因为开启太多定时器了
// 解决方案,让元素只有一个定时器执行
// 清楚以前的定时器,只保留当前的
clearInterval(obj.timer);
obj.timer = setInterval(function() {
//步长公式
// 把步长值改为整数,避免小数问题
// var step = Math.ceil((target - obj.offsetLeft) / 10); //进一法,向上取整
var step = (target - obj.offsetLeft) / 10;
// 判断步长是否大于0,小于0向下取整
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if(obj.offsetLeft == target) {
// 停止动画定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束位置
// if (callback) {
// // 调用函数
// callback();
// }
callback && callback();
}
obj.style.left = obj.offsetLeft + step + 'px';
},15);
}
var arrow_l = document.querySelector('.arrow-l');
var arrow_r = document.querySelector('.arrow-r');
var focus = document.querySelector('.focus');
var focusWidth = focus.offsetWidth;
//鼠标经过就显示和隐藏
focus.addEventListener('mouseenter',function(){
arrow_l.style.display = 'block';
arrow_r.style.display = 'block';
clearInterval(timer);
timer = null; // 清楚定时器变量
})
focus.addEventListener('mouseleave', function(){
arrow_l.style.display = 'none';
arrow_r.style.display = 'none';
timer = setInterval(function(){
//手动调用点击事件(直接调用右侧的点击事件)
arrow_r.click();
},2000)
})
//动态生成小圆圈
var lunbo = focus.querySelector('.lunbo');
var circle = focus.querySelector('.circle');
// var index;
for (var i = 0; i < lunbo.children.length; i++) {
var li = document.createElement('li');
// 自定义属性
li.setAttribute('index', i);
circle.appendChild(li);
//排他思想绑定点击事件
li.addEventListener('click', function() {
for (var i = 0; i < circle.children.length; i++) {
circle.children[i].className = '';
// circle.children[i].index=i;
}
this.className = 'current';
var index = this.getAttribute('index');
//当点击了li就要把当前的index值拿给num
num = index; //全局变量
//当点击了li就要把当前的index值拿给circle1
circle1 = index; //全局变量
// 调用函数
animate(lunbo, - index * focusWidth);
})
}
circle.children[0].className='current';
//右侧箭头点击图片移动开始
// 将第一个小li克隆一份放到轮播的最后
var first = lunbo.children[0].cloneNode(true);
lunbo.appendChild(first);
var num = 0;
var circle1 = 0; //控制小圆圈的播放
//节流阀flag
var flag = true;
arrow_r.addEventListener('click', function() {
if (flag) {
flag = false; //关闭节流阀
if(num == lunbo.children.length -1){
lunbo.style.left = 0;
num = 0;
}
num++;
animate(lunbo, - num * focusWidth, function() {
flag = true; //开启节流阀
});
circle1++;
//如果circle1==4 说明走到了最后我们克隆的这张照片了 我们就复原
if(circle1 == circle.children.length){
circle1 = 0;
}
//先清除其余小圆圈的current类名
for(var i = 0; i < circle.children.length; i++){
circle.children[i].className = '';
}
//留下当前的小圆圈的current类名
circle.children[circle1].className='current';
}
})
//左侧箭头点击图片移动开始
arrow_l.addEventListener('click', function() {
if (flag) {
flag = false; //关闭节流阀
if(num == 0){
num = lunbo.children.length - 1;
lunbo.style.left = - num * focusWidth + 'px';
}
num--;
animate(lunbo, - num * focusWidth, function() {
flag = true; //开启节流阀
});
circle1--;
//如果circle1<0 说明走到了第一张图片
if(circle1 < 0){
circle1 = circle.children.length-1;
}
// circle1 = circle1 < 0 ? circle.children.length-1 : circle1;
//先清除其余小圆圈的current类名
for(var i = 0; i < circle.children.length; i++){
circle.children[i].className = '';
}
//留下当前的小圆圈的current类名
circle.children[circle1].className = 'current';
}
})
//自动播放功能
var timer = setInterval(function(){
//手动调用点击事件(直接调用右侧的点击事件)
arrow_r.click();
},2000)
}
返回顶部
滚动窗口至文档中特定位置
window.scroll(x,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>scroll案例-返回顶部</title>
<style>
.slider-bar {
position: absolute;
left: 50%;
top: 300px;
margin-left: 600px;
width: 45px;
height: 130px;
background-color: rgb(47, 36, 168);
}
a {
text-decoration: none;
color: rgb(136, 13, 13);
}
.w {
width: 1200px;
margin: 10px auto;
}
.header {
height: 150px;
background-color: rgb(120, 11, 27);
}
.banner {
height: 250px;
background-color: rgb(238, 206, 46);
}
.main {
height: 1000px;
background-color: yellowgreen;
}
span {
display: none;
position: absolute;
bottom: 0;
}
</style>
</head>
<body>
<div class="slider-bar">
<span class="goBack">
<a href="javascript:;">返回顶部</a>
</span>
</div>
<div class="header w">头部区域</div>
<div class="banner w">banner区域</div>
<div class="main w">主体部分</div>
<script>
//1. 获取元素
var sliderbar = document.querySelector('.slider-bar');
var banner = document.querySelector('.banner');
// banner.offestTop 就是被卷去头部的大小 一定要写到滚动的外面
var bannerTop = banner.offsetTop;
// 当我们侧边栏固定定位之后应该变化的数值
var sliderbarTop = sliderbar.offsetTop - bannerTop;
// 获取main 主体元素
var main = document.querySelector('.main');
var goBack = document.querySelector('.goBack');
var mainTop = main.offsetTop;
// 2. 页面滚动事件 scroll
document.addEventListener('scroll', function() {
// console.log(11);
// window.pageYOffset 页面被卷去的头部
// console.log(window.pageYOffset);
// 3 .当我们页面被卷去的头部大于等于了 172 此时 侧边栏就要改为固定定位
if (window.pageYOffset >= bannerTop) {
sliderbar.style.position = 'fixed';
sliderbar.style.top = sliderbarTop + 'px';
} else {
sliderbar.style.position = 'absolute';
sliderbar.style.top = '300px';
}
// 4. 当我们页面滚动到main盒子,就显示 goback模块
if (window.pageYOffset >= mainTop) {
goBack.style.display = 'block';
} else {
goBack.style.display = 'none';
}
})
goBack.addEventListener('click', function() {
// window.scroll(0,0);
animate(window, 0);
});
//性能优化,利用对象给不同的元素添加不同的定时器
function animate(obj, target, callback) {
// 不断点击按钮,动画效果会越来越快,因为开启太多定时器了
// 解决方案,让元素只有一个定时器执行
// 清楚以前的定时器,只保留当前的
clearInterval(obj.timer);
obj.timer = setInterval(function() {
//步长公式
// 把步长值改为整数,避免小数问题
// var step = Math.ceil((target - window.pageYOffset) / 10); //进一法,向上取整
var step = (target - window.pageYOffset) / 10;
// 判断步长是否大于0,小于0向下取整
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if(window.pageYOffset == target) {
// 停止动画定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束位置
// if (callback) {
// // 调用函数
// callback();
// }
callback && callback();
}
// obj.style.left = window.pageYOffset + step + 'px';
window.scroll(0, window.pageYOffset + step)
},15);
}
</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>
*{
padding: 0;
margin: 0;
}
.c-nav{
position: relative;
width: 1088px;
margin: 0 auto;
overflow: hidden;
background-color: palegreen;
opacity: .4;
}
ul {
float: left;
width: 100%;
}
li {
float: left;
padding: 0 20px;
line-height: 40px;
height: 40px;
box-sizing: border-box;
list-style: none;
cursor: pointer;
}
a {
text-decoration: none;
color: black;
cursor: pointer;
line-height: 40px;
height: 40px;
font-size: 24px;
}
span {
position: absolute;
top: 3px;
left: 0;
width: 136px;
height: 30px;
background: url('images/bg1.png') no-repeat;
z-index: -3;
}
</style>
<script src="js/animate.js"></script>
</head>
<body>
<div id="c_nav" class="c-nav">
<span class="cloud"></span>
<ul>
<li class="current"><a href="">首页新闻</a></li>
<li><a href="#">师资力量</a></li>
<li><a href="#">活动策划</a></li>
<li><a href="#">企业文化</a></li>
<li><a href="#">招聘信息</a></li>
<li><a href="#">公司简介</a></li>
<li><a href="#">我是佩奇</a></li>
<li><a href="#">啥是佩奇</a></li>
</ul>
</div>
<script>
var cloud = document.querySelector('.cloud');
var c_nav = document.querySelector('.c-nav');
var lis = c_nav.querySelectorAll('li');
// 这个current作为筋斗云的起始位置
var current = 0;
for (var i = 0; i < lis.length; i++) {
// 鼠标经过,把当前小li的位置作为目标值
lis[i].addEventListener('mouseenter', function() {
animate(cloud, this.offsetLeft);
});
// 鼠标离开,回到current
lis[i].addEventListener('mouseleave', function() {
animate(cloud, current);
})
// 当鼠标电机时,就把当前位置作为起始位置
lis[i].addEventListener('click', function() {
current = this.offsetLeft;
})
}
</script>
</body>
</html>
移动端网页特效
触屏事件
1、触摸事件概述
触屏touch事件 | 说明 |
---|---|
touchstart | 手指触摸到一个DOM事件时触发 |
touchmove | 手指在一个DOM元素滑动时触发 |
touchend | 手指从一个DOM元素上移开时触发 |
2、触摸事件对象(TouchEvent)
触摸列表 | 说明 |
---|---|
touches | 正在触摸屏幕的所有手指的一个列表 |
targetTouches ☆ | 正在触摸当前DOM元素上的手指的一个列表 |
changedTouches | 手指状态发生了改变的列表,从无到有,从有到无变化 |
3、clasList属性
clasList属性是HTML5新增属性,返回元素的类名,但只有ie10以上版本支持。得到伪数组形式,可以添加、移除和切换类名。
添加类名:element.classList.add(‘类名’); //追加类
移除类:element.classList.remove(‘类名’);
切换类:element.classList.toggle(‘类名’); // 存在则移除,不存在则添加
4、click延时解决方案
移动端click时间会有300ms的延时,原因是移动端屏幕双击会缩放(double tap to zoom)页面。
解决方案:
1、禁用缩放。
<meta name="viewport" content="user-scalable=no">
2、利用touch事件自己封装这个事件解决300ms延迟。(小于150ms定义为点击)
//封装tap,解决click 300ms 延时
function tap (obj, callback) {
var isMove = false;
var startTime = 0; // 记录触摸时候的时间变量
obj.addEventListener('touchstart', function (e) {
startTime = Date.now(); // 记录触摸时间
});
obj.addEventListener('touchmove', function (e) {
isMove = true; // 看看是否有滑动,有滑动算拖拽,不算点击
});
obj.addEventListener('touchend', function (e) {
if (!isMove && (Date.now() - startTime) < 150) { // 如果手指触摸和离开时间小于150ms 算点击
callback && callback(); // 执行回调函数
}
isMove = false; // 取反 重置
startTime = 0;
});
}
//调用
tap(div, function(){ // 执行代码 });
3、使用插件。fastclick插件解决300ms延迟。
网址:https://github/ftlabs/fastclick
案例
轮播图加返回顶部
<!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>PC端轮播图</title>
<style>
.top {
display: flex;
/* 固定定位跟父级没有关系 以屏幕为准 */
position: fixed;
top: 0;
z-index: 999;
}
.goBack {
display: none;
/*返回顶部的小箭头先隐藏,当页面滚动到某一部分的时候才显示*/
position: fixed;
bottom: 50px;
right: 20px;
width: 30px;
height: 30px;
border: 1px solid rgba(16, 8, 8, 0.2);;
border-radius: 50%;
background: url(images/back.png) no-repeat;
background-size: 25px 25px;
background-position: 2px;
}
.focus{
position: relative;
width: 350px;
height: 180px;
background-color: purple;
margin: 100px auto;
overflow: hidden;
}
.lunbo{
position: absolute;
top: 0;
left: 0;
margin: 0;
margin-left: -100%;
padding: 0;
width: 600%;
/* 父盒子比ul小,一行显示不完,所以不能浮动,必须设置ul的宽度足够宽 */
}
.lunbo li{
float: left;
width: 350px;
height: 180px;
}
.lunbo li img{
width: 350px;
height: 180px;
}
.circle{
position: absolute;
bottom: 6px;
right: 5px;
margin: 0;
}
.circle li{
display: inline-block;
width: 6px;
height: 4px;
border: 1px solid rgba(255, 255, 255, 0.5);
border-radius: 2px;
margin: 0 1px;
cursor: pointer;
transition: all .3s;
}
.circle .current{
width: 15px;
background-color: #fff;
}
ul li{
list-style: none;
}
</style>
<script>
window.addEventListener('load', function() {
var focus = document.querySelector('.focus');
var lunbo = document.querySelector('.lunbo');
var circle = document.querySelector('.circle');
// 1、获取focus宽度
var w = focus.offsetWidth;
// 2、利用定时器自动轮播图片
var index = 0;
var timer = setInterval(function() {
index++;
var translatex = -index * w;
lunbo.style.transition = 'all .4s'; // 过渡效果
lunbo.style.transform = 'translateX(' + translatex + 'px)'; // 移动效果
}, 2000);
// 过渡完成,再去判断 监听过渡完成事件 transitionend
lunbo.addEventListener('transitionend', function() {
// console.log(1);
// 无缝滚动
if (index >= 4) {
index = 0;
// 去掉过渡效果,瞬间跳 让lunbo快速跳到目标位置
lunbo.style.transition = 'none';
// 利用最新的索引号乘以宽度 去滚动图片
var translatex = -index * w;
lunbo.style.transform = 'translateX(' + translatex + 'px)'; // 移动效果
} else if (index < 0) {
index = 3;
// 去掉过渡效果 让lunbo快速跳到目标位置
lunbo.style.transition = 'none';
// 利用最新的索引号乘以宽度 去滚动图片
var translatex = -index * w;
lunbo.style.transform = 'translateX(' + translatex + 'px)'; // 移动效果
}
// 3、小圆点更随变化,排他思想
// 把circle中的current选出来,再去掉
circle.querySelector('.current').classList.remove('current');
// 让当前索引号 的li 加上 current
circle.children[index].classList.add('current');
});
// 4、手指划动轮播图
// 触摸,获取初始坐标
var startX = 0;
var moveX = 0; // 声明同一个全局变量,存放手指移动距离
var flag = false; // 区别用户到底移动了没手指
lunbo.addEventListener('touchstart', function(e) {
startX = e.targetTouches[0].pageX;
// 手指触摸的时候就停止计时器
clearInterval(timer);
});
// 计算手指移动距离,并且移动盒子
lunbo.addEventListener('touchmove', function(e) {
// 计算机移动距离
moveX = e.targetTouches[0].pageX - startX;
// 移动盒子: 原来的位置 + 手指移动的距离
var translatex = -index * w + moveX;
// 手指拖动不需要过渡效果
lunbo.style.transition = 'none';
lunbo.style.transform = 'translateX(' + translatex + 'px)'; // 移动效果
flag = true; // 确定手指移动了
e.preventDefault(); // 阻止手指默认滚动屏幕功能
});
// 手指离开 根据移动距离去判断是回弹还是播放上一张下一张
lunbo.addEventListener('touchend', function(e) {
if(flag) {
if (Math.abs(moveX) > 100) { //移动距离大于100像素
if (moveX > 0) { //如果向右滑,播放上一张,moveX为正
index--;
} else { //如果向左滑,播放下一张,moveX为负
index++;
}
var translatex = -index * w;
lunbo.style.transition = 'all .4s'; //过渡效果
lunbo.style.transform = 'translateX(' + translatex + 'px)'; // 移动效果
} else { // 小于100像素,回弹效果
var translatex = -index * w;
lunbo.style.transition = 'all .2s'; //过渡效果
lunbo.style.transform = 'translateX(' + translatex + 'px)'; // 移动效果
}
}
//手指离开,开启定时器
clearInterval(timer); //清楚之前的,保证只有一个,防止越来越快
// 开启
timer = setInterval(function() {
index++;
var translatex = -index * w;
lunbo.style.transition = 'all .4s'; // 过渡效果
lunbo.style.transform = 'translateX(' + translatex + 'px)'; // 移动效果
}, 2000);
});
// 返回顶部
var goBack = document.querySelector('.goBack');
var nav = document.querySelector('nav');
window.addEventListener('scroll', function() {
if (window.pageYOffset >= nav.offsetTop) {
goBack.style.display = 'block';
} else {
goBack.style.display = 'none';
}
});
goBack.addEventListener('click', function() {
window.scroll(0, 0);
});
})
</script>
</head>
<body>
<div class="top">-------------------------------------------------------------</div>
<!-- 返回顶部模块 -->
<div class="goBack"></div>
<!-- 轮播图 -->
<div class="focus">
<!-- 核心滚动区域 -->
<ul class="lunbo">
<li>
<img src="./images/bg4.png" alt="">
</li>
<li>
<img src="./images/bg1.png" alt="">
</li>
<li>
<img src="./images/bg2.png" alt="">
</li>
<li>
<img src="./images/bg3.png" alt="">
</li>
<li>
<img src="./images/bg4.png" alt="">
</li>
<li>
<img src="./images/bg1.png" alt="">
</li>
</ul>
<!-- 下面的小圆圈 -->
<ul class="circle">
<li class="current"></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<nav>--------------------------------------------------------------------------</nav>
<div class="content">
不对,如果两个对象 x 和 y 满足 x.equals(y) == true,它们的哈希码(hashCode)应当相同。<br>
Java 对于 eqauls 方法和 hashCode 方法是这样规定的:<br>(1)如果两个对象相同(equals 方法返回 true),那
么它们的 hashCode 值一定要相同;<br>(2)如果两个对象的 hashCode 相同,它们并不一定相同。<br>当然,你未必要按照
要求去做,但是如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现在 Set 集合中,同时增加新元素
的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)。<br>
关于 equals 和 hashCode 方法,很多 Java 程序员都知道,但很多人也就是仅仅知道而已,在 Joshua Bloch
的大作《Effective Java》(很多软件公司,《Effective Java》、《Java 编程思想》以及《重构:改善既有代码质量》
是 Java 程序员必看书籍,如果你还没看过,那就赶紧去买一本吧)中是这样介绍 equals 方法的。<br>
首先 equals 方法必须满足自反性(x.equals(x)必须返回 true)、对称性(x.equals(y)返回 true 时,y.equals(x)
也必须返回 true)、传递性(x.equals(y)和 y.equals(z)都返回 true 时,x.equals(z)也必须返回 true)和一致性(当
x 和 y 引用的对象信息没有被修改时,多次调用 x.equals(y)应该得到同样的返回值),而且对于任何非 null 值的引
用 x,x.equals(null)必须返回 false。<br>实现高质量的 equals 方法的诀窍包括:<br>1. 使用==操作符检查"参数是否为这个
对象的引用";<br>2. 使用 instanceof 操作符检查"参数是否为正确的类型";<br>3. 对于类中的关键属性,检查参数传入对象
的属性是否与之相匹配;<br>4. 编写完 equals 方法后,问自己它是否满足对称性、传递性、一致性;<br>5. 重写 equals 时
总是要重写 hashCode;<br>6. 不要将 equals 方法参数中的 Object 对象替换为其他的类型,在重写时不要忘掉
@Override 注解。<br>
</div>
</body>
</html>
移动端常用开发插件
Swiper插件
网址:Swiper中文网-轮播图幻灯片js插件,H5页面前端开发
移动端视频插件
zy.media.js网址:https://github/ireaderlab/zyMedia
其他开发插件
-
superslide:http://www.superslide2/
-
iscroll:https://github/cubiq/iscroll
常用开发框架
框架概述
框架
,顾名思义就是一套架构,它会基于自身的特点向用户提供一套较为完整的解决方案。框架的控制权在框架本身,使用者要按照框架所规定的某种规范进行开发。
插件一般是为了解决某个问题而专门存在,其功能单一,并且比较小。
前端常用的框架有Bootstrap、Vue、Angular、React等。既能开发PC端,也能开发移动端
前端常用的移动端插件有swiper、superslide、iscroll等。
框架:大而全,一整套解决方案
插件︰小而专一,某个功能的解决方案
本地存储
本地存储特性
1、数据存储在用户浏览器中
2、设置、读取方便、甚至页面刷新不丢失数据
3、容量较大,sessionStorage约5M、localStorage约20M
4、只能存储字符串,可以将对象用 JSON.stringify(复杂数据类型) 编码后存储,用 JSON.parse(JSON字符串) 取出
window.sessionStorage
1、生命周期为关闭浏览器窗口
2、在同一个窗口下(页面)下数据可以共享
3、以键值对的形式存储使用
存储数据:
sessionStorage.setItem('key',value)
获取数据:
sessionStorage.getItem('key')
删除数据:
sessionStorage.removeItem('key')
删除所有数据:
sessionStorage.clear()
window.localStorage
1、生命周期永久生效,除非手动删除,即使关闭页面也会存在
2、可以多窗口(页面)共享(同一个浏览器可以共享)
3、以键值对的形式存储使用
存储数据:
localStorage.setItem('key',value)
获取数据:
localStorage.getItem('key')
删除数据:
localStorage.removeItem('key')
删除所有数据:
localStorage.clear()
案例
记住用户名
<input type="text" id="username"> <input type="checkbox" name="" id="remember"> 记住用户名
<script>
var username = document.querySelector('#username');
var remember = document.querySelector('#remember');
if (localStorage.getItem('username')) {
username.value = localStorage.getItem('username');
remember.checked = true;
}
remember.addEventListener('change', function() {
if (this.checked) {
localStorage.setItem('username', username.value);
} else {
localStorage.removeItem('username'); }
})
</script>
本文标签: JavaScriptWebAPIs
版权声明:本文标题:JavaScript-WebAPIs学习记录 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1728025234a1142605.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论