Skip to content

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 页面显示日期和时间

image.png

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 格式化日期的另外方法

image.png

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 实际开发常用

  • dayjs => 当前推荐使用它,体积小,功能全
  • moment.js => 老一点的项目使用,体积稍微大一些,几乎被dayjs取代
javascript
// result  response 返回值,结果
const res = dayjs().format('YYYY-MM-DD HH:mm:ss')
console.log(res)

1.5 时间戳

image.png

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 倒计时

当前时间到未来某个时间的一个倒计时 知识点:

  1. 时间戳的获取 +new Date()
  2. 剩余多少秒 => 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 => 常用

  1. 第一个子元素节点 ul.children[0]
  2. 最后一个子元素节点 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') 追加节点:把新创建的节点放到父元素下

  1. 放到ul最后一个子元素之后 ul.append(li)
  2. 放到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. 移动端事件

移动端的三个事件, 注意、一定要切换成移动端!

  1. touchstart 手指触摸到dom元素时触发
  2. touchmove 手指在dom元素上移动(按住移动)
  3. 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')
    }
  
  }
})