节点可以让我们更好的理清标签元素之间的关系
parentNode 属性,子元素.parentElement 返回的是一个对象
返回最近一级的父节点 找不到返回为null
需求:多个二维码,点击谁,谁关闭
分析:
①:需要给多个按钮绑定点击事件
②:关闭的是当前的父节点
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>
.box{
display: flex;
}
.box img{
border: 1px solid #000;
}
.box i{
width: 10px;
height: 10px;
border: 1px solid #000;
line-height: 7px;
text-align: center;
color: #ccc;
cursor: pointer;
}
style>
head>
<body>
<div class="box">
<img src="./images/456.png" alt="">
<i>xi>
div>
<div class="box">
<img src="./images/456.png" alt="">
<i>xi>
div>
<div class="box">
<img src="./images/456.png" alt="">
<i>xi>
div>
<div class="box">
<img src="./images/456.png" alt="">
<i>xi>
div>
<div class="box">
<img src="./images/456.png" alt="">
<i>xi>
div>
<script>
//获取元素
let i = document.querySelectorAll('i')
//绑定事件
for (let j = 0; j < i.length; j++){
i[j].addEventListener('click',function(){
//关闭当前的二维码,点击谁就关闭谁的爸爸
//没用display='none',这样关掉后不占位,剩下的所有二维码会自动往上移
//this.parentElement返回的是一个对象
this.parentElement.style.visibility = 'hidden'
})
}
script>
body>
html>
<button>点击button>
<ul>
<li>孩子1li>
<li>孩子2li>
<li>孩子3li>
<li>孩子4li>
ul>
<script>
// 获取元素
let btn = document.querySelector('button')
let ul = document.querySelector('ul')
//事件监听
btn.addEventListener('click',function(){
//通过ul控制所有li,ul.children是伪数组,循环
for (let i = 0; i<ul.children.length; i++ ){
ul.children[i].style.color = 'red'
}
})
script>
注意,通过
父元素.children
获得的是一个伪数组,想对里面的元素操作都得先遍历或者取出(父元素.children[0])
兄弟[i].nextElementSibling.style.color = 'red'
创造出一个新的网页元素,创建元素节点方法:
注意标签名只能是标签选择器,如div、p等,不能是类选择器或者ID选择器,如果想创建类选择器:
<script>
let div = document.createElement('div')
div.className = 'box'
script>
要想在界面看到,还得插入到某个父元素中
分析:
①:准备好空的ul 结构
②:根据数据的个数,创建一个新的空li
③:li里面添加内容 img 标题等
④:追加给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>Documenttitle>
<link rel="stylesheet" href="./index.css">
head>
<body>
<div class="box">
<div class="head">
<h3>精品推荐h3>
<p>查看全部p>
div>
<div class="body">
<ul>
ul>
div>
div>
<script>
let data = [
{
src: 'images/course01.png',
title: 'Think PHP 5.0 博客系统实战项目演练',
num: 1125
},
{
src: 'images/course02.png',
title: 'Android 网络动态图片加载实战',
num: 357
},
{
src: 'images/course03.png',
title: 'Angular2 大前端商城实战项目演练',
num: 22250
},
{
src: 'images/course04.png',
title: 'Android APP 实战项目演练',
num: 389
},
{
src: 'images/course05.png',
title: 'UGUI 源码深度分析案例',
num: 124
},
{
src: 'images/course06.png',
title: 'Kami2首页界面切换效果实战演练',
num: 432
},
{
src: 'images/course07.png',
title: 'UNITY 从入门到精通实战案例',
num: 888
},
{
src: 'images/course08.png',
title: 'Cocos 深度学习你不会错过的实战',
num: 590
}
]
//获取元素
let ul = document.querySelector('ul')
for(let i = 0; i<data.length;i++){
//根据数据的个数,创建li
let li = document.createElement('li')
//li添加内容
li.innerHTML = `
${data[i].src}" alt="">
${data[i].title}
高级 •
${data[i].num}人在学习
`
//追加给ul
ul.appendChild(li)
}
script>
body>
html>
原本是将
写到 ul 里面实现数据渲染的,现在可以通过追加实现 html 和 js 分离
特殊情况下,我们新增节点,按照如下操作:
复制一个原有的节点
把复制的节点放入到指定的元素内部
克隆与新建节点一样,需要配合追加节点操作,否则结构中还是不会有此节点
若一个节点在页面中已不需要时,可以删除它
在 JavaScript 原生DOM操作中,要删除元素必须通过父元素删除
如不存在父子关系则删除不成功
删除节点和隐藏节点(display:none) 有区别的: 隐藏节点还是存在的,但是删除,则从html中删除节点
因为时间对象返回的数据我们不能直接使用,所以需要转换为实际开发中常用的格式
需求:将当前时间以:YYYY-MM-DD HH:mm 形式显示在页面
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
div{
width: 300px;
height: 50px;
}
style>
head>
<body>
<div>div>
<script>
setInterval(function(){
//new时间对象
//小括号为空可以得到当前时间
let date = new Date()
let year = date.getFullYear()
let month = date.getMonth()+1
let day = date.getDate()
let hour = date.getHours()
let min = date.getMinutes()
let sec = date.getSeconds()
let div = document.querySelector('div')
div.innerHTML = `${year}-${month}-${day} ${hour}:${min}:${sec}`
},1000)
script>
body>
html>
需求:计算到下课还有多少时间
分析:
①:用将来时间减去现在时间就是剩余的时间
②:核心: 使用将来的时间戳减去现在的时间戳
③:把剩余的时间转换为 天 时 分 秒
注意:
1. 通过时间戳得到是毫秒,需要转换为秒在计算
2. 转换公式:
d = parseInt(总秒数 /60/60 /24); // 计算天数
h = parseInt(总秒数 /60/60 %24) // 计算小时
m = parseInt(总秒数 /60 %60 ); // 计算分数
s = parseInt(总秒数%60); // 计算当前秒数
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>
.countdown {
width: 240px;
height: 305px;
text-align: center;
line-height: 1;
color: #fff;
background-color: brown;
/* background-size: 240px; */
/* float: left; */
overflow: hidden;
}
.countdown .next {
font-size: 16px;
margin: 25px 0 14px;
}
.countdown .title {
font-size: 33px;
}
.countdown .tips {
margin-top: 80px;
font-size: 23px;
}
.countdown small {
font-size: 17px;
}
.countdown .clock {
width: 142px;
margin: 18px auto 0;
overflow: hidden;
}
.countdown .clock span,
.countdown .clock i {
display: block;
text-align: center;
line-height: 34px;
font-size: 23px;
float: left;
}
.countdown .clock span {
width: 34px;
height: 34px;
border-radius: 2px;
background-color: #303430;
}
.countdown .clock i {
width: 20px;
font-style: normal;
}
style>
head>
<body>
<div class="countdown">
<p class="next">今天是p>
<p class="title">下班倒计时p>
<p class="clock">
<span id="hour">00span>
<i>:i>
<span id="minutes">25span>
<i>:i>
<span id="second">20span>
p>
<p class="tips">现在是p>
div>
<script>
//下班倒计时
//获取元素
let h = document.querySelector('#hour')
let m = document.querySelector('#minutes')
let s = document.querySelector('#second')
//先调用一下,因为定时器会有一秒空白期,先调用可以避免
time()
setInterval(time,1000)
function time(){
//现在的时间戳
let now = +new Date()
//指定时间的时间戳
let fu = +new Date('2022-7-19 24:00:00')
//计算时间戳差值,转换为s
let count = (fu-now) / 1000
//转换为时分秒
let hour = parseInt (count/60/60%24)
hour = hour < 10 ? '0'+ hour:hour
let min = parseInt (count/60%60)
min = min < 10 ? '0'+ min:min
let sec = parseInt (count%60)
sec = sec < 10 ? '0'+ sec:sec
//写入时间
h.innerHTML = hour
m.innerHTML = min
s.innerHTML = sec
}
script>
body>
html>
需求1
注册input事件
将文本的内容的长度赋值给对应的数值
表单的maxlength属性可以直接限制在200个数之间
需求2
判断如果内容为空,则提示不能输入为空, 并且直接return
防止输入无意义空格, 使用字符串.trim()去掉首尾空格, 并将表单的value值设置为空字符串
需求3
获取文本域的内容, 赋值给新标签里面的text.value
随机获取数据数组里面的内容, 替换新建立节点的图片和名称
利用时间对象将时间动态化 new Date().toLocaleString()
需求4
在事件处理函数里面获取点击按钮,注册点击事件,删除评论,
放到追加进ul的前面,这样创建元素的同时顺便绑定了删除事件,不用后面再循环绑定很麻烦
(易错点: 必须在事件里面获取,外面获取不到,因为只有发布了的才能被删除)
删除对应的元素
需求5
将表单域内容重置为空
将use里面的内容重置为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>Documenttitle>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul {
list-style: none;
}
/* 文本框 */
.wei {
width: 900px;
margin: 0 auto;
}
.wei textarea {
width: 900px;
height: 112px;
resize: none;
border-radius: 10px;
outline: none;
padding-top: 10px;
padding-left: 20px;
font-size: 18px;
}
/* 底部字数按钮 */
.wei .bottom {
float: right;
}
.wei span {
color: #666;
}
.wei .use {
color: red;
}
.wei button {
width: 100px;
height: 30px;
background-color: rgb(0, 132, 255);
border: 0;
line-height: 30px;
text-align: center;
color: #fff;
font: bold 14px '宋体';
cursor: pointer;
}
button:hover {
background: rgb(0, 225, 255);
}
/* 微博内容发布列表 */
ul {
margin-top: 80px;
}
ul li {
position: relative;
padding: 20px 0;
border-bottom: 1px dashed #ccc;
}
/* 头像昵称发布时间 */
ul li .info {
position: relative;
}
ul li .info .userpic {
width: 80px;
height: 80px;
border-radius: 50%;
}
ul li .info .username {
position: absolute;
top: 15px;
left: 100px;
font: bold 16px '宋体';
}
ul li .info .sendtime {
position: absolute;
top: 40px;
left: 100px;
color: #aaa;
font-size: 12px;
}
/* 发布内容 */
ul li .content {
padding-left: 100px;
color: #666;
}
/* x删除评论 */
ul li .del {
position: absolute;
top: 0;
right: 0;
font-size: 28px;
cursor: pointer;
}
style>
head>
<body>
<div class="wei">
<img src="./images/9.6/tip.png" alt="">
<br>
<textarea placeholder="说点什么吧..." id="area" cols="30" rows="10" maxlength="200">textarea>
<div class="bottom">
<span class="use">0span>
<span>/span>
<span>200span>
<button>发布button>
div>
<div>
<ul>
ul>
div>
div>
<script>
// 模拟数据
let dataArr = [
{ uname: '司马懿', imgSrc: './images/9.5/01.jpg' },
{ uname: '女娲', imgSrc: './images/9.5/02.jpg' },
{ uname: '百里守约', imgSrc: './images/9.5/03.jpg' },
{ uname: '亚瑟', imgSrc: './images/9.5/04.jpg' },
{ uname: '虞姬', imgSrc: './images/9.5/05.jpg' },
{ uname: '张良', imgSrc: './images/9.5/06.jpg' },
{ uname: '安其拉', imgSrc: './images/9.5/07.jpg' },
{ uname: '李白', imgSrc: './images/9.5/08.jpg' },
{ uname: '阿珂', imgSrc: './images/9.5/09.jpg' },
{ uname: '墨子', imgSrc: './images/9.5/10.jpg' },
{ uname: '鲁班', imgSrc: './images/9.5/11.jpg' },
{ uname: '嬴政', imgSrc: './images/9.5/12.jpg' },
{ uname: '孙膑', imgSrc: './images/9.5/13.jpg' },
{ uname: '周瑜', imgSrc: './images/9.5/14.jpg' },
{ uname: '老夫子', imgSrc: './images/9.5/15.jpg' },
{ uname: '狄仁杰', imgSrc: './images/9.5/16.jpg' },
{ uname: '扁鹊', imgSrc: './images/9.5/17.jpg' },
{ uname: '马可波罗', imgSrc: './images/9.5/18.jpg' },
{ uname: '露娜', imgSrc: './images/9.5/19.jpg' },
{ uname: '孙悟空', imgSrc: './images/9.5/20.jpg' },
{ uname: '黄忠', imgSrc: './images/9.5/21.jpg' },
{ uname: '百里玄策', imgSrc: './images/9.5/22.jpg' },
]
// 需求1
// 注册input事件
// 将文本的内容的长度赋值给对应的数值
// 表单的maxlength属性可以直接限制在200个数之间
// 获取元素
let text = document.querySelector('textarea')
let use = document.querySelector('.use')
// 事件监听,输入出发监听
text.addEventListener('input', function () {
//不断获得文本框的字符长度,表单数据获取需要通过元素的value获取,而对于div则需要通过innerHTML获取
use.innerHTML = text.value.length
})
// 需求2
// 判断如果内容为空,则提示不能输入为空, 并且直接return
// 防止输入无意义空格, 使用字符串.trim()去掉首尾空格, 并将表单的value值设置为空字符串
//获取元素
let btn = document.querySelector('button')
btn.addEventListener('click', function () {
if (text.value.trim() === '') {
text.value = ''
use.innerHTML = 0
return alert('内容不能为空')
}
// 需求3
// 获取文本域的内容, 赋值给新标签里面的text.value
// 随机获取数据数组里面的内容, 替换新建立节点的图片和名称
// 利用时间对象将时间动态化 new Date().toLocaleString()
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min)
}
let random = getRandom(0, dataArr.length - 1)
let ul = document.querySelector('ul')
let li = document.createElement('li')
li.innerHTML = `
${dataArr[random].imgSrc} alt="">
${dataArr[random].uname}
${new Date().toLocaleString()}
${text.value}
X
`
// 需求4
// 在事件处理函数里面获取点击按钮, 注册点击事件
// (易错点: 必须在事件里面获取, 外面获取不到)
// 删除对应的元素
// 因为li只新建还没追加,在document里面找不到,所以在li里面找
let del = li.querySelector('.del')
del.addEventListener('click',function(){
ul.removeChild(li)
})
ul.insertBefore(li, ul.children[0])
// 需求5
// 将表单域内容重置为空
// 将use里面的内容重置为0
text.value = ''
use.innerHTML = 0
})
script>
body>
html>
解析(Parser)HTML,生成DOM树(DOM Tree)
同时解析(Parser) CSS,生成样式规则 (Style Rules)
根据DOM树和样式规则,生成渲染树(Render Tree)
进行布局 Layout(回流/重排):根据生成的渲染树,得到节点的几何信息(位置,大小)
进行绘制 Painting(重绘): 根据计算和获取的信息进行整个页面的绘制
Display: 展示在页面上
回流(重排)
当 Render Tree 中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或全部文档的过程称为回流。
重绘
由于节点(元素)的样式的改变并不影响它在文档流中的位置和文档布局时(比如:color、background-color、outline等), 称为重绘。
重绘不一定引起回流,而回流一定会引起重绘
会导致回流(重排)的操作:
页面的首次刷新
浏览器的窗口大小发生改变
元素的大小或位置发生改变
改变字体的大小
内容的变化(如:input框的输入,图片的大小)
激活css伪类 (如::hover)
脚本操作DOM(添加或者删除可见的DOM元素)
简单理解,影响到布局了,就会有回流
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>购物车全选功能title>
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
a {
text-decoration: none;
color: #666;
}
body {
background: #fff;
color: #666;
font-size: 14px;
}
input {
outline: none;
}
.clearfix::before,
.clearfix::after {
content: '';
display: block;
clear: both;
}
.clearfix {
*zoom: 1;
}
style>
<style>
table {
width: 800px;
margin: 0 auto;
border-collapse: collapse;
}
th {
font: normal 14px/50px '宋体';
color: #666;
}
th,
td {
border: none;
text-align: center;
border-bottom: 1px dashed #ccc;
}
input[type='checkbox'] {
width: 13px;
height: 13px;
}
tbody p {
position: relative;
bottom: 10px;
}
tbody .add,
tbody .reduce {
float: left;
width: 22px;
height: 22px;
border: 1px solid #ccc;
text-align: center;
background: none;
outline: none;
cursor: pointer;
}
tbody input[type='text'] {
width: 50px;
float: left;
height: 18px;
text-align: center;
}
tbody .count-c {
width: 98px;
margin: 0 auto;
}
button[disabled] {
color: #ddd;
cursor: not-allowed;
}
tbody tr:hover {
background: #eee;
}
tbody tr.active {
background: rgba(241, 209, 149, 0.945);
}
.controls {
width: 790px;
margin: 10px auto;
border: 1px solid #ccc;
line-height: 50px;
padding-left: 10px;
position: relative;
}
.controls .del-all,
.controls .clear {
float: left;
margin-right: 50px;
}
.controls p {
float: right;
margin-right: 100px;
}
.controls span {
color: red;
}
.controls .pay {
position: absolute;
right: 0;
width: 80px;
height: 54px;
background: red;
font: bold 20px/54px '宋体';
color: #fff;
text-align: center;
bottom: -1px;
}
.controls .total-price {
font-weight: bold;
}
style>
head>
<body>
<div class="car">
<table>
<thead>
<tr>
<th><input type="checkbox" id="all" />全选th>
<th>商品th>
<th>单价th>
<th>商品数量th>
<th>小计th>
<th>操作th>
tr>
thead>
<tbody id="carBody">
<tr>
<td>
<input class="s_ck" type="checkbox" readonly />
td>
<td>
<img src="./images/01.jpg" />
<p>牛奶p>
td>
<td class="price">5¥td>
<td>
<div class="count-c clearfix">
<button class="reduce" disabled>-button>
<input type="text" value="1" />
<button class="add">+button>
div>
td>
<td class="total">5¥td>
<td>
<a href="javascript:" class="del">删除a>
td>
tr>
<tr>
<td>
<input class="s_ck" type="checkbox" />
td>
<td>
<img src="./images/01.jpg" />
<p>牛奶p>
td>
<td class="price">10¥td>
<td>
<div class="count-c clearfix">
<button class="reduce" disabled>-button>
<input type="text" value="1" />
<button class="add">+button>
div>
td>
<td class="total">10¥td>
<td>
<a href="javascript:" class="del">删除a>
td>
tr>
<tr>
<td>
<input class="s_ck" type="checkbox" />
td>
<td>
<img src="./images/01.jpg" />
<p>牛奶p>
td>
<td class="price">20¥td>
<td>
<div class="count-c clearfix">
<button class="reduce" disabled>-button>
<input type="text" value="1" />
<button class="add">+button>
div>
td>
<td class="total">20¥td>
<td>
<a href="javascript:" class="del">删除a>
td>
tr>
<tr>
<td>
<input class="s_ck" type="checkbox" />
td>
<td>
<img src="./images/01.jpg" />
<p>牛奶p>
td>
<td class="price">35¥td>
<td>
<div class="count-c clearfix">
<button class="reduce" disabled>-button>
<input type="text" value="1" />
<button class="add">+button>
div>
td>
<td class="total">35¥td>
<td>
<a href="javascript:" class="del">删除a>
td>
tr>
tbody>
table>
<div class="controls clearfix">
<a href="javascript:" class="del-all">删除所选商品a>
<a href="javascript:" class="clear">清理购物车a>
<a href="javascript:" class="pay">去结算a>
<p>
已经选中<span id="totalCount">4span>件商品;总价:<span id="totalPrice" class="total-price">0¥span>
p>
div>
div>
<script>
// + - 删除是相同的,一一对应的 可以用一个for来遍历绑定事件
//加
let add = document.querySelectorAll('.add')
//减
let reduce = document.querySelectorAll('.reduce')
//删除
let del = document.querySelectorAll('.del')
//每个商品个数
let input = document.querySelectorAll('.count-c input')
//单价
let price = document.querySelectorAll('.price')
//每个商品总价
let total = document.querySelectorAll('.total')
//商品盒子
let carBody = document.querySelector('#carBody')
//总共商品数
let goods = document.querySelector('#totalCount')
//总价
let money = document.querySelector('#totalPrice')
for (let i = 0; i < add.length; i++) {
//1、加号
add[i].addEventListener('click', function () {
input[i].value++
reduce[i].disabled = false
total[i].innerHTML = parseInt(price[i].innerHTML) * input[i].value + '¥'
result()
})
//2、减号
reduce[i].addEventListener('click', function () {
input[i].value--
if (input[i].value <= 1) {
reduce[i].disabled = true
}
total[i].innerHTML = parseInt(price[i].innerHTML) * input[i].value + '¥'
result()
})
//3、删除
del[i].addEventListener('click', function () {
//没办法用carBody.removeChild(carBody.children[i]),例如第一次点击删除1想删除1号商品
// 第二次想点击删除2的删除2号商品但这个时候商品2是父节点的第一个孩子
carBody.removeChild(this.parentNode.parentNode)
result()
})
}
function result() {
let sum = 0
let num = 0
//删除后,需要重新获取每个商品个数和总价,否则还是删除之前的数,如删除1号商品后,
//对2号商品操作会显示在3号商品,因为此时3号商品才是第二个孩子
//每个商品个数
let input = document.querySelectorAll('.count-c input')
//每个商品总价
let total = document.querySelectorAll('.total')
for (let i = 0; i < total.length; i++) {
sum += +parseInt(total[i].innerHTML)
num += +input[i].value
}
goods.innerHTML = num
money.innerHTML = sum + '¥'
}
// div span ul li 标签 有文字内容 怎么得到或则设置文字内容呢 元素.innerText 元素.innerHTML
// 表单 input 单选 复选 textarea select 怎么得到或则设置值 表单的value
// 特殊的 button 是通过inner来设置
script>
body>
html>