日期对象
实例化
//创建一个时间对象并获取时间
// 获得当前时间
const date = new date()
//获得指定时间
const date = new date('2024-8-10 ')
时间对象方法
//页面显示时间
<div></div>
<script>
//获取对象
const div = document.querySelector('div')
//自定义函数
// function myDate() {
// //获取时间
// const date = new Date()
// let h = date.getHours()
// let m = date.getMinutes()
// let s = date.getSeconds()
// h = h < 10 ? '0' + h : h
// m = m < 10 ? '0' + m : m
// s = s < 10 ? '0' + s : s
// return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日 ${h}:${m}:${s}`
// }
// div.innerHTML = myDate()
// setInterval(function () {
// div.innerHTML = myDate()
// }, 1000)
const date = new Date()
div.innerHTML = date.toLocaleString()
setInterval(function () {
const date = new Date()
div.innerHTML = date.toLocaleString()
}, 1000)
// div.innerHTML = date.toLocaleString() //2024/8/2 14:59:17
// div.innerHTML = date.toLocaleDateString() //2024/8/2
// div.innerHTML = date.toLocaleTimeString() //15:00:44
// div.innerHTML = date.toLocaleString()
</script>
时间戳
指1970年01月01日00时00分00秒起至现在的毫秒数,它是一种特殊的计量时间的方式。
算法:将来的时间戳 - 现在的时间戳 = 剩余时间毫秒数(剩余时间毫秒数 转换为 剩余时间的 年月日时分秒 就是 倒计时时间)
三种方式获取时间戳:
(1)getTime() 方法 const date = new date()
console.log(date.getTime())
(2)简写 +new Date() console.log(+new date())
(3)Date.now() console.log(date.now())
date.now()无需实例化,但是只能得到当前的时间戳, 而前面两种可以返回指定时间的时间戳。
毕业倒计时效果
<div class="countdown">
<p class="next">今天是2024年8月9日</p>
<p class="title">下班倒计时</p>
<p class="clock">
<span id="hour">00</span>
<i>:</i>
<span id="minutes">25</span>
<i>:</i>
<span id="scond">20</span>
</p>
<p class="tips">18:30:00下课</p>
</div>
<script>
//函数封装
function getCountTime() {
//得到当前时间戳
const now = +new Date()
//得到未来时间戳
const last = +new Date('2024-8-10 18:30:00')
//剩余时间戳
const count = (last - now) / 1000
// let d = parseInt(count / 60 / 60 / 24)
let h = parseInt(count / 60 / 60 % 24)
h = h < 10 ? '0' + h : h
let m = parseInt(count / 60 % 60)
m = m < 10 ? '0' + m : m
let s = parseInt(count % 60)
s = s < 10 ? '0' + s : s
//获取时间盒子
const hour = document.querySelector('#hour')
const minutes = document.querySelector('#minutes')
const scond = document.querySelector('#scond')
hour.innerHTML = h
minutes.innerHTML = m
scond.innerHTML = s
}
//先调用一次
getCountTime()
//开启定时器
setInterval(getCountTime, 1000)
节点操作
DOM 节点
定义:DOM树里每一个内容都称之为节点
节点类型:
1.元素节点
(1)所有的标签 比如 body、 div
(2)html 是根节点
(3)可以更好的让我们理清标签元素之间的关系
2.属性节点 所有的属性 比如 href
3.文本节点 所有的文本
4.其他
查找节点
节点关系:针对的找亲戚返回的都是对象
父节点查找:
子元素.parentNode
返回最近一级的父节点 找不到返回为null
子节点查找:
(1)childNodes
获得所有子节点、包括文本节点(空格、换行)、注释节点等
(2)children 属性 (重点)
- 父元素.children
- 仅获得所有元素节点
- 返回的还是一个伪数组
兄弟关系查找:
(1)下一个兄弟节点 nextElementSibling 属性
(2)上一个兄弟节点 previousElementSibling 属性
增加节点
创建节点
// 创建元素节点
document.createElement('标签名')
追加节点
//追加节点
//插入到父元素的最后一个子元素
父元素.appendChild(要插入的元素)
// 插入到父元素中某个子元素的前面
父元素.insertBefore(要插入的元素,在哪个元素面前)
ul.insertBefore(li,ul.children[0])
//克隆节点
元素.cloneNode(布尔值)
//cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值。
//若为true,则代表克隆时会包含后代节点一起克隆。
//若为false,则代表克隆时不包含后代节点,默认为false。
学成在线案例渲染
<!-- 4. box核心内容区域开始 -->
<div class="box w">
<div class="box-hd">
<h3>精品推荐</h3>
<a href="#">查看全部</a>
</div>
<div class="box-bd">
<ul class="clearfix">
</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
},
]
//获取ul
const ul = document.querySelector('.box-bd ul')
//根据数据的个数 创建对应的Li
for (let i = 0; i < data.length; i++) {
//创建li
const li = document.createElement('li')
//把内容写进li
li.innerHTML = `
<a href="#">
<img src=${data[i].src} alt="">
<h4>
${data[i].title}
</h4>
<div class="info">
<span>高级</span> • <span>${data[i].num}</span>人在学习
</div>
</a>
`
//追加Li
ul.appendChild(li)
}
</script>
删除节点
在 JavaScript 原生DOM操作中,要删除元素必须通过父元素删除。
//删除元素
父元素.removeChildren(要删除的元素)
注意:(1)如不存在父子关系则删除不成功
(2)删除节点和隐藏节点(display:none) 的区别: 隐藏节点还是存在的,但是删除,则从html中删除节点。
M端事件
移动端也有自己独特的地方。比如触屏事件 touch(也称触摸事件),Android 和 IOS 都有。
常见的触屏事件如下:
JS插件
插件: 就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果。
官网: https://www.swiper.com.cn/
注意: 多个swiper同时使用的时候, 类名需要注意区分。
综合案例
游乐园轮播图
//通过插件引入的代码块
<!-- 轮播图模块 -->
<!-- Swiper -->
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">
<a href="#"><img src="./uploads/banner_1.png" alt=""></a>
</div>
<div class="swiper-slide">
<a href="#"><img src="./uploads/banner_1.png" alt=""></a>
</div>
<div class="swiper-slide">
<a href="#"><img src="./uploads/banner_1.png" alt=""></a>
</div>
<div class="swiper-slide">
<a href="#"><img src="./uploads/banner_1.png" alt=""></a>
</div>
<div class="swiper-slide">
<a href="#"><img src="./uploads/banner_1.png" alt=""></a>
</div>
</div>
<!-- Add Pagination -->
<div class="swiper-pagination"></div>
</div>
</div>
<!-- 引入js文件 -->
<script src="./js/flexible.js"></script>
<script src="./js/swiper.min.js"></script>
<!-- Initialize Swiper -->
<script>
var swiper = new Swiper('.swiper-container', {
pagination: {
el: '.swiper-pagination',
},
autoplay: {
delay: 3000,//3秒切换一次
},
});
</script>
学生信息表案例
<h1>新增学员</h1>
<form class="info" autocomplete="off">
姓名:<input type="text" class="uname" name="uname" />
年龄:<input type="text" class="age" name="age" />
性别:
<select name="gender" class="gender">
<option value="男">男</option>
<option value="女">女</option>
</select>
薪资:<input type="text" class="salary" name="salary" />
就业城市:<select name="city" class="city">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
<option value="曹县">曹县</option>
</select>
<button class="add">录入</button>
</form>
<h1>就业榜</h1>
<table>
<thead>
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>薪资</th>
<th>就业城市</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!--
<tr>
<td>1001</td>
<td>欧阳霸天</td>
<td>19</td>
<td>男</td>
<td>15000</td>
<td>上海</td>
<td>
<a href="javascript:">删除</a>
</td>
</tr>
-->
</tbody>
</table>
<script>
// 获取元素
const uname = document.querySelector('.uname')
const age = document.querySelector('.age')
const gender = document.querySelector('.gender')
const salary = document.querySelector('.salary')
const city = document.querySelector('.city')
const tbody = document.querySelector('tbody')
// 获取所有带有name属性的 元素
const items = document.querySelectorAll('[name]')
// 声明一个空的数组, 增加和删除都是对这个数组进行操作
const arr = []
// 录入模块
// 表单提交事件
const info = document.querySelector('.info')
info.addEventListener('submit', function (e) {
// 阻止默认行为 不跳转
e.preventDefault()
// 这里进行表单验证 如果不通过,直接中断,不需要添加数据
// 先遍历循环
for (let i = 0; i < items.length; i++) {
if (items[i].value === '') {
return alert('输入内容不能为空')
}
}
// 创建新的对象
const obj = {
stuId: arr.length + 1,
uname: uname.value,
age: age.value,
gender: gender.value,
salary: salary.value,
city: city.value
}
// console.log(obj)
// 追加给数组里面
arr.push(obj)
// console.log(arr)
// 清空表单 重置
this.reset()
// 调用渲染函数
render()
})
// 渲染函数 因为增加和删除都需要渲染
function render() {
// 先清空tbody 以前的行 ,把最新数组里面的数据渲染完毕
tbody.innerHTML = ''
// 遍历arr数组
for (let i = 0; i < arr.length; i++) {
// 生成 tr
const tr = document.createElement('tr')
tr.innerHTML = `
<td>${arr[i].stuId}</td>
<td>${arr[i].uname}</td>
<td>${arr[i].age}</td>
<td>${arr[i].gender}</td>
<td>${arr[i].salary}</td>
<td>${arr[i].city}</td>
<td>
<a href="javascript:" data-id=${i}>删除</a>
</td>
`
// 追加元素 父元素.appendChild(子元素)
tbody.appendChild(tr)
}
}
// 删除操作
// 事件委托 tbody
tbody.addEventListener('click', function (e) {
if (e.target.tagName === 'A') {
// 得到当前元素的自定义属性 data-id
// console.log(e.target.dataset.id)
// 删除arr 数组里面对应的数据
arr.splice(e.target.dataset.id, 1)
console.log(arr)
// 从新渲染一次
render()
}
})
</script>
补充:重绘和回流
回流(重排)
当 Render Tree 中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或全部文档的 过程称为 回流。(简单理解影响到布局了,就会有回流。)
重绘
由于节点(元素)的样式的改变并不影响它在文档流中的位置和文档布局时(比如:color、background-color、 outline等), 称为重绘。
重绘不一定引起回流,而回流一定会引起重绘。