一 轮播图
var t var count =0 var Odiv = document.querySelector('.box') //大盒子 var Obox = document.querySelector('.box2') //图片的大盒子 var Odian = document.querySelectorAll('.bb') //按钮集合 var Oimg = document.querySelectorAll('.box2 p') //图片集合 var Ozuo = document.querySelector('#sp1') //左翻页 var Oyou = document.querySelector('#sp2') //右翻页 // 调取自动播放函数 zd() // 自动播放 function zd(){ // 创建一个定时器 t = setInterval(function(){ // count自增 count++ // 当count到最后一张图的角标时,回滚为0 if(count >= Odian.length){ count =0 } // 调取显示函数 qc() },1000) } // 点击切换照片 // 遍历照片的数量 for(var i = 0;i<Oimg.length;i++){ // 因为照片没有角标,给照片增加一个自定义属性qq 并按顺序赋值 Odian[i].qq = i // 当点击这个值对应的按钮时,显示qq.的值对应的照片 Odian[i].onclick = function(){ clearInterval(t) count = this.qq qc() } } // 上翻页 Ozuo.onclick = function(){ // 翻页的时候清除定时器 clearInterval(t) // 上翻页是往回翻,所以count自减 count-- // 当count到第一张照片的值时再次点击回滚到最后一张 if(count < 0){ count =Oimg.length-1 } // 调取点击显示函数 qc() } // 下翻页 Oyou.onclick = function(){ // 翻页的时候清除定时器 clearInterval(t) // 下翻页是往后翻。所以count自增 count++ // 当count到最后一张照片时再次点击回滚到第一张 if(count>Oimg.length-1){ count = 0 } qc() } // 鼠标移入事件,鼠标移入的时候清除定时器并且调取点击显示函数 Odiv.onmouseover =function(){ clearInterval(t) qc() } // 鼠标移出事件,鼠标移出时调取自动播放函数 Odiv.onmouseout=function(){ zd() } // 封装的显示函数 function qc(){ // 先清除所有照片以及按钮上点击时附加的属性 for(var i =0 ; i < Oimg.length ; i++){ Oimg[i].classList.remove('active') Odian[i].classList.remove('show') } // 再给当前点击的按钮以及照片附加属性 Oimg[count].classList.add('active') Odian[count].classList.add('show') }
轮播图的设计思路是,先在Css样式表中添加一个属性为点击后的样式,一般用active表示,
再在js点击事件时用classlist 给标签添加这个属性值,即可完成换图,切换的效果,同时设置一个定时器每隔一段时间换一张图片。
二 DOM新增的方法
DOM新增的方法主要有两种
1,innerHTML 直接插入,语法示例 arr.innerHTML=‘heelo world’
或者 arr.innerHTML=‘<p>heelo world</p>’
2, 先创建一个文本节点,createTextNode()
再创建一个标签节点,createElement()
最后再将文本节点通过
在最后面插入 appendChild()
在指定的元素前面插入 insertBefore(要插入的元素 , 指定的元素)
两种方式插入标签,示例如下
var oDiv = document.querySelector('.a') ; // oDiv.innerHTML = '<p>666</p>' // 1 创建一个标签 createElement var oP = document.createElement('p') ; console.log(oP); // 2 创建一个文本节点 var oText = document.createTextNode('666'); console.log(oText); // 3 添加子元素 把文本插入标签中 oP.appendChild(oText) ; // 4 把p插入div中 oDiv.appendChild(oP) 5,将标签插入到span标签前面去 var oSpan = document.querySelector('span') ; oDiv.insertBefore(oP , oSpan)
两种方法的区别!
innerHTML 只能解析字符串 而且插入方式较为单一,但是比较简单。
appendChild() 插入方式繁琐,复杂,但是插入的是一个对象,方便修改。
总结,简单元素可以直接用innerHTML插入,复杂数据用appendChild() 插入
三 DOM 删除
// DOM删除 remove() 删除自己和所有的子元素 removeChild() 删除指定的子元素,只能删除子元素,不能删除子元素下面的元素,即后代元素 innerHTML = '' 删除所有的子元素 示例: var oDiv = document.querySelector('.a') ; oDiv.remove() var oP = document.querySelector('p') ; oDiv.removeChild(oP) oDiv.innerHTML = ''
四 DOM替换
// 替换子元素 // replaceChild(new , old) 前面是要替换进去的元素,后面是被替换的元素 // 拿到div var oDiv = document.querySelector('.a') ; // 拿到span标签 var oSpan = document.querySelector('span') ; // 新建一个strong标签 var oStrong = document.createElement('strong') ; // strong标签的内容为888 oStrong.innerHTML = '888' // 把div中的 span 换成 strong oDiv.replaceChild(oStrong , oSpan)
五 DOM找父辈元素
// 找父元素 parentNode // 拿到所有的按钮 var oBtns = document.querySelectorAll('button') ; // 创建一个循环点击事件 for(var i = 0 ; i < oBtns.length ; i++) { // 点击的时候控制台打印这个元素的父元素 oBtns[i].onclick = function () { console.log(this.parentNode); } }
六 DOM找子元素或者子节点
// childNodes 子节点 --- 包含所有的文本,换行,标签,注释等等 // children 子元素 --- 只包含标签 // firstElementChild 第一个子元素 // lastElementChild 最后一个子元素 // firstChild 第一个子节点 // lastChild 最后一个子节点 var oDiv = document.querySelector('.a') ; console.log(oDiv.childNodes); console.log(oDiv.children); console.log(oDiv.children[0]); console.log(oDiv.firstChild)
childNodes 因为包括注释,节点,换行都在包含在内,所以用的很少。
七 DOM找同级元素
// previousElementSibling 前一个标签兄弟元素 // nextElementSibling 后一个标签兄弟 // previousSibling 前一个兄弟节点 // nextSibling 后一个兄弟节点 var oDiv = document.querySelector('.a') ; var oP = document.querySelector('p') ; // 以上代码可以连续使用,使用两次代表离自己两个远的同级标签 console.log(oP.previousElementSibling.previousElementSibling);
八 克隆节点
// cloneNode() 克隆节点 , 默认只复制标签 // cloneNode(true) 克隆节点,包含子元素 var oDiv = document.querySelector('.a') ; var oDiv2 = oDiv.cloneNode(true) ; console.log(oDiv2); // 把div标签添加到HTML上 document.body.appendChild(oDiv2)
九 查找元素
查找元素一般用于链接CSS
// 用ES6查找 var oDiv = document.querySelector('.a'); // 用class名查找 var oDiv = document.getElementsByClassName('.a')[0] ; // 选择器是从右向左查找的,当后代选择的越多时,查找需要的计算量越大 // 后代选择器酌情使用,最好不要使用三代以上的后代选择器 var oP = document.querySelector('.a p') ; // document的意思是从 HTML里开始查找 // 从指定的父元素中查找的话时间会快很多,这也是对代码优化的一种方式 var oP = oDiv.querySelector('p') ;
十 文档碎片处理,重绘与回流
当你改变页面的样式时,必定需要重新渲染页面,这就引发了重绘与回流
重绘与回流的区别是,重绘只需要改变页面的颜色,而回流是将页面擦掉重新渲染
所以回流必定会引发重绘,但是重绘不一定会引发回流。
重绘和回流都会影响页面的响应速度,并且回流的代价比重绘要大很多
但是这个方法解决不了,只能优化,即尽可能的减少回流和重绘的次数。
任何的DOM操作都会引发回流。
同样是在页面中添加P标签 方法1是生成一个P标签就添加一次,这样我们就要渲染100次页面 for(var i = 0 ; i < 100 ; i++) { var oP = document.createElement('p') ; oP.innerHTML = i ; // DOM操作有100次 document.body.appendChild(oP) } 而第二种方法是先创建一个字符串,用他把生成出来的P标签接住,等100个P标签生成完了,再 一次性通过DOM方法加入到页面中,这种方法回流次数少,请求速度,程序响应速度都会提升 var res = '' ; for(var i = 0 ; i < 100 ; i++) { res += '<p>' + i + '</p>' } // DOM实际上只有一次 document.body.innerHTML += res ;
js有一个专门的处理方法叫 fragment 即文档碎片处理,
把需要大量进行DOM操作的数据存入一个对象,等数据添加完了再一次性回流页面。
代码如下:
var fragment = document.createDocumentFragment() ; console.log(fragment); for(var i = 0 ; i < 1000 ; i++) { var oP = document.createElement('p') ; oP.innerHTML = i ; fragment.appendChild(oP) } document.body.appendChild(fragment)
此方法与上述第二种方法异曲同工,但是更为复杂,因为这种操作方式会将 fragment 定义为一个对象,而不是一个字符串。
十一 自制留言板
<!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>
<style>
* {
padding: 0;
margin: 0;
}
body {
width: 100%;
height: 100%;
background: rgb(65, 65, 63);
}
.bacground {
width: 700px;
height: 100%;
background: white;
margin: auto;
margin-top: 20px;
}
.head,
.pop-head {
height: 50px;
font-size: 20px;
text-align: center;
line-height: 50px;
}
.name {
width: 640px;
height: 40px;
font-size: 20px;
margin: 10px 28px;
line-height: 50px;
border-radius: 8px;
border: 2px solid rgb(139, 137, 137);
outline: none;
}
.content,
.pop-reply {
width: 640px;
height: 150px;
font-size: 22px;
margin: 10px 28px;
border: 2px solid rgb(139, 137, 137);
outline: none;
border-radius: 8px;
resize: none;
}
.btn,
.pop-btn {
float: right;
height: 30px;
margin-right: 28px;
border-radius: 6px;
outline: none;
font-size: 20px;
padding: 0 20px;
background: rgb(169, 238, 255);
}
h3 {
font-size: 20px;
color: rgb(102, 102, 102);
background: rgb(205, 221, 248);
margin-top: 50px;
line-height: 50px;
text-indent: 30px;
font-weight: 545;
}
li {
list-style: none;
width: 640px;
font-size: 22px;
margin: 15px 30px;
}
.message-head {
display: flex;
}
.message-head .photo {
width: 70px;
height: 70px;
background: rgb(6, 109, 134);
display: inline-block;
border-radius: 50%;
text-align: center;
line-height: 70px;
overflow: hidden;
}
.message-head .time {
margin-left: 12px;
}
.liuyan,
.reply p {
width: 560px;
/* height: 76px; */
line-height: 50px;
display: block;
background: rgb(205, 221, 248);
font-size: 20px;
margin-left: 80px;
border-radius: 8px;
text-indent: 15px;
}
.delete {
width: 60px;
height: 30px;
display: block;
line-height: 30px;
margin-left: 580px;
/* margin-bottom: 0px; */
border-radius: 6px;
outline: none;
font-size: 15px;
background: rgb(169, 238, 255);
}
.answer {
width: 60px;
height: 30px;
display: block;
line-height: 30px;
margin-top: -29px;
margin-left: 515px;
border-radius: 6px;
outline: none;
font-size: 15px;
background: rgb(169, 238, 255);
}
.popup {
width: 100vw;
height: 100vh;
position: fixed;
background: rgba(0, 0, 0, .3);
left: 0;
top: 0;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
display: none;
}
.pop-content {
width: 700px;
background: #fff;
border-radius: 10px;
overflow: hidden;
padding-bottom: 20px;
}
.reply p {
margin-top: 10px;
background: rgba(100, 100, 100, .1);
}
</style>
<body>
<div class="bacground">
<div class="head">留言板</div>
<input class="name" type="text" placeholder="请输入您的昵称">
<textarea class="content" placeholder="请保持言论文明......"></textarea>
<button class="btn">留言</button>
<h3>大家在说</h3>
<ul class="text">
<!-- <li>
<div class="message-head">
<span class="photo">系统</span>
<p class="time">2019-9-27 0:47:38</p>
</div>
<p class="liuyan">测试留言</p>
<div class="reply">
<p>测试回复</p>
</div>
<button class="delete">Delete</button>
<button class="answer">Answer</button>
</li> -->
</ul>
</div>
<div class="popup">
<div class="pop-content">
<div class="pop-head">回复板</div>
<textarea class="pop-reply" placeholder="请保持言论文明......"></textarea>
<button class="pop-btn huiFu">回复</button>
<button class="pop-btn quXiao">取消</button>
</div>
</div>
</body>
<script>
// 创造一个函数,用于获取元素
function $(ab) {
return document.querySelector(ab)
}
// 获取当前时间
var date = shjian()
// 获取留言按钮
var Obtn = $('.btn')
// 获取昵称
var Otext = $('.text')
// 创建一个点击事件
Obtn.onclick = function () {
// 点击后获取输入的昵称以及留言
var Oname = $('.name').value
var Ocontent = $('.content').value
// 判断昵称和留言是否为空,如果为空则提示并结束此次事件
if (Oname === '' || Ocontent === '') {
alert('输入内容不能为空')
return
}
// 优化回流,先创造一个文本接住需要插入的内容,获取完全后再渲染页面一起插入
Oli = document.createElement('li')
Oli.innerHTML = `
<div class="message-head">
<span class="photo">${Oname}</span>
<p class="time">${date}</p>
</div>
<p class="liuyan">${Ocontent}</p>
<div class="reply">
</div>
<button class="delete">Delete</button>
<button class="answer">Answer</button>
`
Otext.appendChild(Oli)
// 设置一个变量为10
var x = 10
// 点击留言后留言样式变为10秒
Obtn.innerHTML = x + '秒'
// 点击后留言按钮禁用
Obtn.disabled = true
// 设置一个定时器
var t = setInterval(function () {
// 变量自减
x--
// 同时每秒刷新剩余秒数
Obtn.innerHTML = x + '秒'
// 当倒计时走到0秒时,解除禁用,清除倒计时,并且可再次留言
if (x == 0) {
Obtn.innerHTML = '留言'
clearTimeout(t)
Obtn.disabled = false
}
}, 1000)
// 获取删除留言按钮元素
var Odelete = document.querySelectorAll(".delete")
// 创建一个循环点击事件,点击删除按钮时删掉此按钮父元素的所有标签
for (var i = 0; i < Odelete.length; i++) {
Odelete[i].onclick = function () {
this.parentNode.remove()
}
}
// 获取回复留言按钮
var Oanswer = document.querySelectorAll('.answer')
// 创建一个循环点击事件
for(var i = 0; i<Oanswer.length;i++){
// 点击回复留言时将之前隐藏的留言框显示
Oanswer[i].onclick = function(){
$('.popup').style.display = 'flex'
// 为了知道回复的是哪个留言框,一开始就确定位置
var abc = this.previousElementSibling.previousElementSibling
// 点击的取消的时候隐藏留言框
$('.quXiao').onclick = function(){
$('.popup').style.display = 'none'
}
// 点击回复执行以下代码
$('.huiFu').onclick = function () {
// 设置一个变量接住刚刚输入的值
var huiFuContent = $('.pop-reply').value ;
// 假如 输入值不为空执行一下代码
if(huiFuContent) {
// 优化节流,创建一个文本p标签接住刚刚得到的值
var oP = document.createElement('p') ;
oP.innerHTML = huiFuContent ;
// 将这个标签插入页面
abc.appendChild(oP)
}
// 关闭回复留言框
$('.popup').style.display = 'none' ;
}
}
}
}
// 创建一个时间函数,获取当前时间,通过修改样式可读性变高
function shjian(){
var a1 = new Date()
var year = a1.getFullYear()
var month = a1.getMonth()+1
var date = a1.getDate()
var week = a1.getDay()
var hour = a1.getHours()
var mintue = a1.getMinutes()
var Second = a1.getSeconds()
if(Second<10){
Second = '0'+Second
}
var z = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六']
return year + '-' + month + '-' + date + ' '+ hour + ':' + mintue + ':' + Second +' ' +z[week]
}