1. 日期对象
1.1 日期对象
:::tips const date = new Date() date => 就是我们的日期对象,我们可以通过这个对象得到当前的日期和时间 :::
实例化:通过构造函数生成实例对象的过程; 或者说以new Date() 这种形式生成具体的某个对象的过程
实例:实际的例子,具体的某个对象
javascript
// 1. 实例化日期对象
// 1.1 得到当前的日期和时间
const date = new Date()
console.log(date)
// 1.2 得到指定的日期和时间
const date1 = new Date('2026-12-12')
console.log(date1)
// 2. 格式化日期对象-转换成开发中常见的日期和时间格式
const myDate = new Date()
const year = myDate.getFullYear() // 年
const month = myDate.getMonth() + 1 // 月
const day = myDate.getDate() // 日
console.log(myDate.getFullYear())
console.log(myDate.getMonth() + 1) // 得到当前的月份 0-11 需要加1
console.log(myDate.getDate()) // 一个月的几号
console.log(myDate.getDay()) // 0-6 // 0表示星期天
// 3. 获取时分秒
const h = myDate.getHours()
const m = myDate.getMinutes()
const s = myDate.getSeconds()
console.log(h, m , s)
// 返回当前的年月日时分秒
console.log(`${year}年${month}月${day}日`)
1.2 页面显示日期和时间
javascript
// 1. 封装一个 getDateTime函数,里面格式化时间对象
const getDateTime = function(){
// 1. 先要得到一个日期对象
const date = new Date()
// 2. 获取年月日
const year = date.getFullYear() // 年
const month = date.getMonth() + 1 // 月
const day = date.getDate() // 日
// 3. 获取时分秒
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
// 4. 函数要写return返回一个值
return `${year}年${month}月${day}号 ${h}:${m}:${s}`
}
// 显示到页面中,获取元素
const box = document.querySelector('.box')
// 让盒子一开始就显示时间 防止有1秒的空白期
box.innerHTML = getDateTime()
// 开启定时器
setInterval(function(){
box.innerHTML = getDateTime()
}, 1000)
1.3 格式化日期的另外方法
javascript
// const date = new Date()
// console.log(date.toLocaleString()) 包含日期和事件 => 使用它
// console.log(date.toLocaleDateString()) 只有日期
// console.log(date.toLocaleTimeString()) 只有时间
// 但是上面的格式是固定的~~~
function getTime(){
// 每次都需要重新获取一个新的日期对象
const date = new Date()
return date.toLocaleString()
}
// 获取box
const box = document.querySelector('.box')
// 一开始调用一次,防止1s的空白
box.innerHTML = getTime()
setInterval(function(){
box.innerHTML = getTime()
}, 1000)
1.4 实际开发常用
javascript
// result response 返回值,结果
const res = dayjs().format('YYYY-MM-DD HH:mm:ss')
console.log(res)
1.5 时间戳
javascript
// 获取时间戳的三种方式
// 1. getTime()
// const date = new Date()
// console.log(date.getTime())
console.log(new Date().getTime())
// 2. +new Date() 推荐使用 ==> 1. 简单 2. 可以传入日期时间
console.log(+new Date())
console.log(+new Date('2099-12-01'))
// 3. Date.now() 得到当前日期的时间戳 ==> 只能得到当前
// console.log(Date.now())
1.6 倒计时
当前时间到未来某个时间的一个倒计时 知识点:
- 时间戳的获取 +new Date()
- 剩余多少秒 =>
const time = (future - now) / 1000
javascript
// 转换公式
// d = parseInt(总秒数 / 60 / 60 / 24) // 计算天数
// h = parseInt(总秒数 / 60 / 60 % 24) // 计算小时
// m = parseInt(总秒数 / 60 % 60) // 计算分数
// s = parseInt(总秒数 % 60) // 计算当前秒数
const getCountTime = function(){
// 1. 先得到当前的事件戳
const now = +new Date()
// 2. 在得到未来的时间戳
const future = +new Date('2023-08-19 08:00:00')
// 3. 得到剩余的时间差
const time = (future - now) / 1000
// 4. 转换为 天 时分秒
let d = parseInt(time / 60 / 60 / 24)
let h = parseInt(time / 60 / 60 % 24)
let m = parseInt(time / 60 % 60)
let s = parseInt(time % 60)
// 5. 补0
d = d < 10 ? '0' + d : d
h = h < 10 ? '0' + h : h
m = m < 10 ? '0' + m : m
s = s < 10 ? '0' + s : s
// 6. 将天 时 分 秒 显示到span盒子中
document.querySelector('#day').innerHTML = d
document.querySelector('#hour').innerHTML = h
document.querySelector('#minutes').innerHTML = m
document.querySelector('#second').innerHTML = s
}
// 调用一次
getCountTime()
setInterval(getCountTime, 1000)
2. 节点相关
2.1 DOM树
dom树 : 描述的是DOM节点之间的层级关系,比如父子关系,兄弟关系
- 节点 node : 页面上所有的内容都叫做节点 ,包括 元素节点、属性节点、文本节点、注释节点
- 元素 element : 页面上所有的标签都叫做元素
- 文档 document : 一个页面就是一个文档
2.2 父节点
**子元素.parentNode ** 返回的是最近的一级父元素节点,找不到返回null
javascript
// 查找父节点
// node.parentNode 返回的是最近的一级父元素节点,找不到返回null
// console.log(closeBtn.parentNode)
const son = document.querySelector('.son')
// 可以多次点出爷爷和祖祖
console.log(son.parentNode.parentNode)
2.3 子元素节点
语法:父节点.children => 常用
- 第一个子元素节点 ul.children[0]
- 最后一个子元素节点 ul.children[ul.children.length - 1]
javascript
// 1. 查询子节点
const ul = document.querySelector('ul')
console.log(ul.children)
// 第一个子元素节点
// console.log(ul.children[0])
// 最后一个子元素节点
// console.log(ul.children[ul.children.length - 1])
2.4 兄弟元素节点
下一个兄弟元素节点 el.nextElementSibling 上一个兄弟元素节点 el.previousElementSibling
javascript
// 查询兄弟元素节点
// 获取ul中的第2个li标签
const li_2 = document.querySelector('ul li:nth-child(2)')
console.log(li_2)
// 下一个兄弟元素节点 next Element Sibling
console.log(li_2.nextElementSibling)
// 上一个兄弟元素节点
console.log(li_2.previousElementSibling)
2.5 创建节点-追加节点
创建节点:
const li = document.createElement('li')
追加节点:把新创建的节点放到父元素下
- 放到ul最后一个子元素之后
ul.append(li)
- 放到ul中第一个子元素之前
ul.prepend(li)
javascript
// 1. 创建节点
const li = document.createElement('li')
console.log(li)
li.innerHTML = '我是刚刚诞生的小li'
// 2. 追加给父元素
const ul = document.querySelector('ul')
// 2.1 父元素.append() 放到父元素的最后
ul.append(li)
// 2.1 父元素.prepend(要添加的元素) 放到ul中第一个子元素之前
const first_li = document.createElement('li')
first_li.innerHTML = '我是第一个li'
ul.prepend(first_li)
2.6 删除节点
如果一个节点在页面中不需要时,可以删除它 el.remove() => 把某个元素从dom树中移除
注意:display:none 是隐藏元素,元素在dom树中还存在
javascript
// 1. 删除节点 注意:remove()会将元素节点从dom树上移除
const del = document.querySelector('.remove')
del.remove()
// 2. display:none 隐藏元素 页面看不见,但是dom中还存在这个标签元素!
const none = document.querySelector('.none')
none.style.display = 'none'
3.知识点扩充
3.1. 移动端事件
移动端的三个事件, 注意、一定要切换成移动端!
- touchstart 手指触摸到dom元素时触发
- touchmove 手指在dom元素上移动(按住移动)
- touchend 手指在dom元素上离开时触发
javascript
// 触摸事件 注意:一定要切换到移动端,才会有这个事件
const box = document.querySelector('.box')
// 1. 手指触屏开始事件 touchstart
box.addEventListener('touchstart', function(){
console.log('我触摸了一下这个dom')
})
// 2. 手指触屏滑动事件 touchmove
box.addEventListener('touchmove', function(){
console.log('我在这个dom上移动')
})
// 3. 手指触屏结束事件 touchend
box.addEventListener('touchend', function(){
console.log('建国说:摸完就跑')
})
3.2 forEach遍历数组
javascript
// forEach遍历数组
// arr.forEach(cbFn)
// 作用:forEach() 方法对数组的每个元素执行一次给定的函数。
// forEach接收一个回调函数cbFn, cbFn又接收两个参数
// 1. cbFn的第一个参数,el ==> 表示数组里面的元素
// 2. cbFn的第二个参数,i ==> 表示数组中每个元素的索引号
// forEach(function(element) { /* … */ })
// forEach(function(element, index) { /* … */ })
const arr = ['green', 'red', 'skyblue', 'yellow', 'purple', 'brown']
// arr.forEach(function(el, i){
// console.log(el, i)
// })
arr.forEach(function(el){
console.log(el)
})
3.3 subString()-从字符串中截取子串
javascript
// substring 截取字符串
// 语法: 字符串.substring(起始索引号,[结束索引号])
// str.substring(indexStart[, indexEnd])
// 作用:从字符串中截取一个字段出来
// 截取 前闭后开 [0, 2) ==> 截取索引号为0,1的字符串
// 注意:1. 索引号是 [start, end) , 结束索引号不包含在截取的字符串中
// 2. 如果indexEnd不传,第二个参数不写,会取到最后
const str = '建国说,改革春风吹满地,中国人民真争气'
console.log(str.substring(0, 2))
console.log(str.substring(6, 11))
console.log(str.substring(4))
4. 综合案例
01 作业 网页时钟
javascript
// 角度换算: 公式复制即可
// 小时角度公式:小时 * 30 + 分钟 / 60 * 30
// 分钟角度公式:分钟* 6 + 秒 / 60 * 6
// 秒角度公式: 当前秒数 * 6
// 获取时分秒的div,那个指针
const h = document.querySelector('.hh')
const m = document.querySelector('.mm')
const s = document.querySelector('.ss')
const clock = function(){
const date = new Date()
// 获取时分秒
const hh = date.getHours()
const mm = date.getMinutes()
const ss = date.getSeconds()
// 根据转换公式,让时分秒的div旋转
h.style.transform = `rotate(${hh * 30 + mm / 60 * 30}deg)`
m.style.transform = `rotate(${mm* 6 + ss / 60 * 6}deg)`
s.style.transform = `rotate(${ss * 6}deg)`
}
// 第一次也要调用一下
clock()
// 开启定时器
setInterval(clock, 1000)
02 作业创建英雄列表
javascript
const btn = document.querySelector('#create')
const ul = document.querySelector('.list')
const render = function(){
// 事件处理程序
let str = ''
arr.forEach(function(el){
str += `
<li><img src="uploads/heros/${el.imgSrc}" title="${el.name}"></li>
`
})
// ul.innerHTML = str
}
btn.addEventListener('click', render)
03 携程旅游
javascript
// 1. 用JS的方式给每个span添加自定义属性
const spans = document.querySelectorAll('.tab span')
spans.forEach(function(el, i){
el.setAttribute('data-id', i)
})
const box = document.querySelector('.tab')
const ul = document.querySelector('.tab_theme')
// 2. 以事件委托的方式绑定事件
box.addEventListener('click', function(e){
// if (e.target.tagName !=='SPAN') return
if(e.target.tagName === 'SPAN') {
// 1. 上面span标签的排他
box.querySelector('.active').classList.remove('active')
e.target.classList.add('active')
// 2. 点击span标签, 渲染下面的列表
// 我怎么知道我点的是第几个span
// 渲染数组中对应下标数据
render(e.target.dataset.id)
} // end if
})
// 3. 封装一个渲染对应数组下标数据的函数
const render = function(i){
// 渲染数据
let str = ''
// 取对象中的数组
arr[i].data.forEach(function(el){
str += `
<li>
<a href="#">
<div class="pic_add"><img alt="${el.name}" src="${el.url}"></div>
<div class="city_name">${el.name}</div>
</a>
</li>
`
})
ul.innerHTML = str
}
// 4. 让一开始自动触发第一个
spans[0].click()
4. 通讯录案例
todo01 通讯录渲染业务
javascript
// 1.渲染业务 封装到函数 render里面
const box = document.querySelector('.address-book')
const render = function(){
let str = ''
// 遍历数组
arr.forEach(function(el, i){
str += `
<div class="item">
<p class="circle">${el.name.substring(el.name.length - 1)}</p>
<p class="name">${el.name}</p>
<p class="tel">${el.tel}</p>
<a class="del" href="javascript:;" ">
<i class=" iconfont icon-shanchutianchong" data-index="${i}"></i>
</a>
</div>
`
})
box.innerHTML = str
// todo 02
// 当可以获取到item的时候,就可以给每个item具有滑动效果了
initSwipe()
}
render()
todo02 滑动效果
javascript
// 函数提升,用function声明的函数,会在代码执行前,提升到当前作用域的最前面
// 如果用const声明的函数,不会提升
function initSwipe(){
const items = document.querySelectorAll('.item')
// 让每一个item都具有滑动的效果
items.forEach(function(el){
// start forEach
new AlloyFinger(el, {
// 滑动时候触发的函数
swipe: function (e) {
// 如果往左滑动,则让item盒子添加 active类,就可以让盒子左侧移动了
if (e.direction === 'Left') {
// 滑动的时候排他
const old = document.querySelector('.address-book .active')
old&&old.classList.remove('active')
el.classList.add('active')
} else {
el.classList.remove('active')
}
}
})
})
// end forEach
}
todo03 新增用户
javascript
// 3. 新增业务
const nameIpt = document.querySelector('#name')
const telIpt = document.querySelector('#tel')
const addBtn = document.querySelector('#add')
addBtn.addEventListener('click', function(){
if (nameIpt.value === '' || telIpt.value === '') {
// 只要name和tel有一个为空,就提示
return alert('姓名和电话不能为空哦~')
}
// !false ==> true
if (!nameIpt.value || !telIpt.value) {
// nameIpt如果为空,!nameIpt.value 就为true
// 只要!nameIpt.value 或 !telIpt.value 有一个为true , 就提示
return alert('姓名和电话不能为空哦~')
}
})
javascript
const nameIpt = document.querySelector('#name')
const telIpt = document.querySelector('#tel')
const addBtn = document.querySelector('#add')
addBtn.addEventListener('click', function(){
if (nameIpt.value === '' || telIpt.value === '') {
// 只要name和tel有一个为空,就提示
return alert('姓名和电话不能为空哦~')
}
// 得到用户输入的值,往数组中push一个新的对象
arr.push({
name: nameIpt.value,
tel: telIpt.value
})
// 调用render函数,渲染页面
render()
nameIpt.value = ''
telIpt.value = ''
})
todo04 删除业务
javascript
// 滑动点击删除
// 给公共父元素绑定点击事件
box.addEventListener('click', function(e){
if (e.target.tagName === 'I'){
const res = confirm('你真的要删除我吗?')
if (res){
// 利用自定义属性,取到点击哪个i,进而知道要删除数组中哪个元素
console.log(e.target.dataset.index)
// 从数组中删除元素 arr.splice(要删除的索引号 , 1)
arr.splice(e.target.dataset.index, 1)
render()
} else {
// 移动回去 i标签的父亲的父亲就是那个item
e.target.parentNode.parentNode.classList.remove('active')
}
}
})