JavaScript学习笔记——第二篇

目录

二,APIs

3.定时器-间歇函数

3.1开启定时器

3.2关闭定时器

阅读注册协议倒计时:

 案例:轮播图定时版

4.事件监听

京东点击关闭顶部广告:

随机点名案例:

拓展-事件监听版本:

4.1事件类型:

 鼠标事件:轮播图点击切换

焦点事件:小米搜索框

键盘事件:评论字数统计

 4.2事件对象

语法:如何获取

 事件对象常用属性:

案例:评论回车发布

4.3环境对象

4.4回调函数

案例:tab栏切换

全选文本框案例1 :

5.事件流

5.1事件流和两个阶段说明

5.2事件捕获

5.3事件冒泡

5.4阻止冒泡

5.5阻止默认行为

5.6事件解绑

5.7鼠标经过事件的区别:

6.事件委托

案例:tab栏切换-事件委托版

知识点补充—css自定义属性:

7.其他事件

7.1页面加载事件

Load事件:

DOMContentLoaded事件:

7.2元素滚动事件

获取位置-scrollLeft和scrollTop(属性):

滚动到指定的坐标-scrollTo()

 电梯导航案例:

7.3页面尺寸事件

获取元素宽高:

元素尺寸于位置:

 元素尺寸于位置-尺寸获取宽高:

仿东京固定导航栏案例

实现bilibili点击小滑块移动效果

元素尺寸于位置-尺寸 获取位置:

总结:

8.日期对象 

8.1实例化

8.2时间对象方法

案例-页面显示时间

8.3时间戳

 三种方式获取时间戳:

9.节点操作

9.1DOM节点

9.2查找节点

 父节点查找:

点击关闭广告案例:

子节点查找:

 兄弟关系查找:

9.3增加节点

 创建节点:

追加节点:

案例:

​编辑

学成在线案例渲染:

克隆节点:

9.4删除节点

 10.M端事件

11.swiper插件--第124p

12.Window对象

12.1BOM(浏览器对象模型)

12.2定时器-延时函数

5秒钟之后消失的广告:

12.3JS执行机制

12.4location对象

5秒钟之后跳转的页面

12.5navigator对象

​编辑12.6histroy.对象 

13.本地存储

13.1本地存储介绍

13.2本地存储分类-localStorage

​编辑

12.3本地存储分类-sessionStorage

  13.4存储复杂数据类型

14.数组map和join方法

15.正则表达式

15.1介绍

15.2语法

15.3元字符

用户名验证案例:

15.4修饰符

过滤敏感字


二,APIs

3.定时器-间歇函数

3.1开启定时器

setInterval(函数,时间间隔)

作用:每隔一段时间调用这个函数

间隔时间单位是毫秒

<script>
  //方法一
setInterval(function(){
  console.log('一秒打印一次')
},1000)
  //方法二
function fn(){
    console.log('一秒打印一次')
}
setInterval(fn,1000)
</script>

3.2关闭定时器

let 变量名 = setInterval(函数,间隔时间)
clearInterval(变量名)
function fn(){
    console.log('一秒打印一次')
}
let n = setInterval(fn,1000)
//关闭定时器
clearInterval(n)
阅读注册协议倒计时:

需求:按钮60秒之后才可以使用

分析:

1.一开始先把按钮禁用(disabled属性)

2.一定要获取元素

3.函数内处理逻辑  

  •  秒数开始减减
  • 按钮里面的文字跟着一起变化
  • 如果秒数等于0 停止定时器 里面文字变为 同意 后按钮可以点击
<body>
  <textarea>
    1.一开始先把按钮禁用(disabled属性)

    2.一定要获取元素

    3.函数内处理逻辑  

  </textarea>
  <br>
  <button >已经阅读用户协议(10秒)</button>
  <script>
    const button = document.querySelector('button')
    //禁用按钮
    button.disabled = true
    //这里一定要用let 倒计时
    let i = 10
    let n = setInterval(function(){
      i--
      button.innerHTML = `已经阅读用户协议(${i}秒)`
      if (i === 0){
        clearInterval(n)
        button.innerHTML = `同意`
        button.disabled = false
      }
    },1000)
  </script>
</body>

 案例:轮播图定时版

需求:每隔一秒钟切换一个图片

分析:

1.准备一个数组对象,里面包含详细信息

2.获取元素

3.设置定时函数

  • 设置一个变量++
  • 找到变量对应的对象
  • 更改图片,文字信息
  • 激活小圆点:移除上一个高亮的类名,当前变量对应的小圆点添加类

4.处理图片自动复原从头播放(放到变量++后面,紧挨)

  • 如果图片播放到最后一张,就是大于等于数组的长度
  • 则把变量重置为0 
<!DOCTYPE html>
<html lang="en">

<head>
  <title>轮播图点击切换</title>
  <style>
    * {
      box-sizing: border-box;
    }

    .slider {
      width: 560px;
      height: 400px;
      overflow: hidden;
    }

    .slider-wrapper {
      width: 100%;
      height: 320px;
    }

    .slider-wrapper img {
      width: 100%;
      height: 100%;
      display: block;
    }

    .slider-footer {
      height: 80px;
      background-color: rgb(100, 67, 68);
      padding: 12px 12px 0 12px;
      position: relative;
    }

    .slider-footer .toggle {
      position: absolute;
      right: 0;
      top: 12px;
      display: flex;
    }

    .slider-footer .toggle button {
      margin-right: 12px;
      width: 28px;
      height: 28px;
      appearance: none;
      border: none;
      background: rgba(255, 255, 255, 0.1);
      color: #fff;
      border-radius: 4px;
      cursor: pointer;
    }

    .slider-footer .toggle button:hover {
      background: rgba(255, 255, 255, 0.2);
    }

    .slider-footer p {
      margin: 0;
      color: #fff;
      font-size: 18px;
      margin-bottom: 10px;
    }

    .slider-indicator {
      margin: 0;
      padding: 0;
      list-style: none;
      display: flex;
      align-items: center;
    }

    .slider-indicator li {
      width: 8px;
      height: 8px;
      margin: 4px;
      border-radius: 50%;
      background: #fff;
      opacity: 0.4;
      cursor: pointer;
    }

    .slider-indicator li.active {
      width: 12px;
      height: 12px;
      opacity: 1;
    }
  </style>
</head>

<body>
  <div class="slider">
    <div class="slider-wrapper">
      <img src="./slider01.jpg" alt="" />
    </div>
    <div class="slider-footer">
      <p>对人类来说会不会太超前了?</p>
      <ul class="slider-indicator">
        <li class="active"></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
      </ul>
      <div class="toggle">
        <button class="prev">&lt;</button>
        <button class="next">&gt;</button>
      </div>
    </div>
  </div>
  <script>
    // 1. 初始数据
    const sliderData = [
      { url: './slider01.jpg', title: '对人类来说会不会太超前了?', color: 'rgb(100, 67, 68)' },
      { url: './slider02.jpg', title: '开启剑与雪的黑暗传说!', color: 'rgb(43, 35, 26)' },
      { url: './slider03.jpg', title: '真正的jo厨出现了!', color: 'rgb(36, 31, 33)' },
      { url: './slider04.jpg', title: '李玉刚:让世界通过B站看到东方大国文化', color: 'rgb(139, 98, 66)' },
      { url: './slider05.jpg', title: '快来分享你的寒假日常吧~', color: 'rgb(67, 90, 92)' },
      { url: './slider06.jpg', title: '哔哩哔哩小年YEAH', color: 'rgb(166, 131, 143)' },
      { url: './slider07.jpg', title: '一站式解决你的电脑配置问题!!!', color: 'rgb(53, 29, 25)' },
      { url: './slider08.jpg', title: '谁不想和小猫咪贴贴呢!', color: 'rgb(99, 72, 114)' },
    ]
    //2.获取元素
    let i = 0
    //3.设置定时器
    setInterval(function () {
      i++
      //无缝衔接位置
      if(i >= sliderData.length){
        i =0
      }
      //更改图片
      const img = document.querySelector('.slider-wrapper img')
      img.src = sliderData[i].url
      //更改标题
      const p = document.querySelector('.slider-footer p')
      p.innerHTML = sliderData[i].title
      //删除前一个小圆点
      const activeClass = document.querySelector('.slider-footer .slider-indicator .active')
      activeClass.classList.remove('active')
      //激活小圆点
      const li = document.querySelector(`.slider-indicator li:nth-child(${i + 1})`)
      li.classList.add('active')

    }, 1000)
  </script>
</body>

</html>

4.事件监听

目标:能够给DOM元素添加事件监听

什么是事件?

事件是在编程时系统内发生的动作或者发生的事情

比如用户在网页上单击一个按钮

什么是事件监听?

就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为绑定事件或者注册事件,比如鼠标经过显示下拉菜单,比如点击可以播放轮播图等等

语法:

元素对象.addEventListener('事件类型',要执行的函数)

事件监听三要素:

  • 事件源:那个DOM元素被事件触发了,要获取DOM元素
  • 事件类型:用什么方式触发,比如鼠标单击click,鼠标经过mouseover等
  • 事件调用的函数:要做什么事

举例说明:

//1.事件类型要加引号
//2.函数是点击之后再去执行,每次点击都会执行一次

<body>
<button>按钮</button>
  <script>
    const btn = document.querySelector('button')
    btn.addEventListener ('click',function(){
      console.log('点击')
    })
  </script>
</body>
京东点击关闭顶部广告:
<head>
  <style>
    .box {
      position: relative;
      width: 1000px;
      height: 200px;
      background-color: pink;
      margin: 100px auto;
      text-align: center;
      font-size: 50px;
      line-height: 200px;
      font-weight: 700;
    }

    .box1 {
      position: absolute;
      right: 20px;
      top: 10px;
      width: 20px;
      height: 20px;
      background-color: skyblue;
      text-align: center;
      line-height: 20px;
      font-size: 16px;
      cursor: pointer;
    }
  </style>
</head>

<body>
  <div class="box">
    我是广告
    <div class="box1">X</div>
  </div>
  <script>
    // 1. 获取事件源
    const box1 = document.querySelector('.box1')
    //  关闭的是大盒子
    const box = document.querySelector('.box')
    // 2. 事件侦听
    box1.addEventListener('click', function () {
      box.style.display = 'none'
    })
  </script>
</body>

随机点名案例:

分析:

点击开始按钮随机抽取数组的一个数据,放到页面中

点击结束按钮删除数组当前抽中的一个数据

当抽取到最后一个数据的时候,两个按钮同时禁用(写点开始里面,只剩最后一个数据不用抽了)

核心:利用定时器快速展示,停止定时器结束展示

<!DOCTYPE html>
<html lang="en">

<head>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        h2 {
            text-align: center;
        }

        .box {
            width: 600px;
            margin: 50px auto;
            display: flex;
            font-size: 25px;
            line-height: 40px;
        }

        .qs {

            width: 450px;
            height: 40px;
            color: red;

        }

        .btns {
            text-align: center;
        }

        .btns button {
            width: 120px;
            height: 35px;
            margin: 0 50px;
        }
    </style>
</head>

<body>
    <h2>随机点名</h2>
    <div class="box">
        <span>名字是:</span>
        <div class="qs">这里显示姓名</div>
    </div>
    <div class="btns">
        <button class="start">开始</button>
        <button class="end">结束</button>
    </div>

    <script>
        // 数据数组
        const arr = ['马超', '黄忠', '赵云', '关羽', '张飞']
        //点击开始按钮随机抽取的一个数组放到页面中
        const qs = document.querySelector('.qs')
        const start = document.querySelector('.start')
        let timerId = 0
        //随机号也要全局变量
        let random = 0
        start.addEventListener('click', function () {
            //设置定时器快速刷新
            //将timerId设置为全局变量,在下面关闭定时器时才能使用
            timerId = setInterval(function () {
                random = Math.floor(Math.random() * arr.length)
                qs.innerHTML = arr[random]
                console.log(arr[random])
            }, 35)
            //如果数组里面只有一个值了,还需要抽取吗?不需要 让两个按钮禁用就可以
            if(arr.length === 1){
                start.disabled = true
                end.disabled = true
            }
        })

        //点击结束按钮删除数组当中的一个数据
        const end = document.querySelector('.end')
        end.addEventListener('click', function () {
            clearInterval(timerId)
            arr.splice(random, 1)
        })
    </script>
</body>

</html>
拓展-事件监听版本:
  • DOM L0

事件源.on事件= function() {}

  • DOM L2

事件源.addEventListener(事件,事件处理函数)

  • 区别

on方式会被覆盖,addEventListener方式可绑定多次,拥有事件更多特性,推荐使用 

4.1事件类型:

 鼠标事件:轮播图点击切换

分析:

  1. 右侧按钮点击,变量++,如果大于等于8,则复原0
  2. 左侧按钮点击,变量--,如果小于0,则复原最后一张
  3. 鼠标经过暂停定时
  4. 鼠标离开开启定时
<!DOCTYPE html>
<html lang="en">

<head>
  <title>轮播图点击切换</title>
  <style>
    * {
      box-sizing: border-box;
    }

    .slider {
      width: 560px;
      height: 400px;
      overflow: hidden;
    }

    .slider-wrapper {
      width: 100%;
      height: 320px;
    }

    .slider-wrapper img {
      width: 100%;
      height: 100%;
      display: block;
    }

    .slider-footer {
      height: 80px;
      background-color: rgb(100, 67, 68);
      padding: 12px 12px 0 12px;
      position: relative;
    }

    .slider-footer .toggle {
      position: absolute;
      right: 0;
      top: 12px;
      display: flex;
    }

    .slider-footer .toggle button {
      margin-right: 12px;
      width: 28px;
      height: 28px;
      appearance: none;
      border: none;
      background: rgba(255, 255, 255, 0.1);
      color: #fff;
      border-radius: 4px;
      cursor: pointer;
    }

    .slider-footer .toggle button:hover {
      background: rgba(255, 255, 255, 0.2);
    }

    .slider-footer p {
      margin: 0;
      color: #fff;
      font-size: 18px;
      margin-bottom: 10px;
    }

    .slider-indicator {
      margin: 0;
      padding: 0;
      list-style: none;
      display: flex;
      align-items: center;
    }

    .slider-indicator li {
      width: 8px;
      height: 8px;
      margin: 4px;
      border-radius: 50%;
      background: #fff;
      opacity: 0.4;
      cursor: pointer;
    }

    .slider-indicator li.active {
      width: 12px;
      height: 12px;
      opacity: 1;
    }
  </style>
</head>

<body>
  <div class="slider">
    <div class="slider-wrapper">
      <img src="./slider01.jpg" alt="" />
    </div>
    <div class="slider-footer">
      <p>对人类来说会不会太超前了?</p>
      <ul class="slider-indicator">
        <li class="active"></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
      </ul>
      <div class="toggle">
        <button class="prev">&lt;</button>
        <button class="next">&gt;</button>
      </div>
    </div>
  </div>
  <script>
    // 1. 初始数据
    const sliderData = [
      { url: './slider01.jpg', title: '对人类来说会不会太超前了?', color: 'rgb(100, 67, 68)' },
      { url: './slider02.jpg', title: '开启剑与雪的黑暗传说!', color: 'rgb(43, 35, 26)' },
      { url: './slider03.jpg', title: '真正的jo厨出现了!', color: 'rgb(36, 31, 33)' },
      { url: './slider04.jpg', title: '李玉刚:让世界通过B站看到东方大国文化', color: 'rgb(139, 98, 66)' },
      { url: './slider05.jpg', title: '快来分享你的寒假日常吧~', color: 'rgb(67, 90, 92)' },
      { url: './slider06.jpg', title: '哔哩哔哩小年YEAH', color: 'rgb(166, 131, 143)' },
      { url: './slider07.jpg', title: '一站式解决你的电脑配置问题!!!', color: 'rgb(53, 29, 25)' },
      { url: './slider08.jpg', title: '谁不想和小猫咪贴贴呢!', color: 'rgb(99, 72, 114)' },
    ]
    let i = 0
    let time = 0
    const p = document.querySelector('.slider-footer p')
    const img = document.querySelector('.slider-wrapper img')

    // 左侧按钮点击,变量--,如果小于0,则复原最后一张
    const prev = document.querySelector('.toggle .prev')
    prev.addEventListener('click', function () {
      i--
      if (i < 0) {
        i = 7
      }
      // 更改图片,文字信息
      img.src = sliderData[i].url
      p.innerHTML = sliderData[i].title
      // 激活小圆点:移除上一个高亮的类名,当前变量对应的小圆点添加类
      const activeClass = document.querySelector('.slider-indicator .active').classList.remove('active')
      const active = document.querySelector(`.slider-indicator li:nth-child(${i + 1})`).classList.add('active')
    })

    //右侧按钮点击,变量++,如果大于等于8,则复原0
    const next = document.querySelector('.toggle .next')
    next.addEventListener('click', function () {
      i++
      if (i >= sliderData.length) {
        i = 0
      }
      // 更改图片,文字信息
      img.src = sliderData[i].url
      p.innerHTML = sliderData[i].title
      // 激活小圆点:移除上一个高亮的类名,当前变量对应的小圆点添加类
      const activeClass = document.querySelector(' .slider-indicator .active').classList.remove('active')
      const active = document.querySelector(`.slider-indicator li:nth-child(${i + 1})`).classList.add('active')
    })

    // 鼠标经过暂停定时
    const slider = document.querySelector('.slider')
    slider.addEventListener('mouseenter', function () {
      clearInterval(time)
    })

    // 鼠标离开开启定时
    slider.addEventListener('mouseleave', function () {
      time = setInterval(function () {
        i++
        //无缝衔接位置
        if (i >= sliderData.length) {
          i = 0
        }
        // 更改图片,文字信息
        img.src = sliderData[i].url
        p.innerHTML = sliderData[i].title
        // 激活小圆点:移除上一个高亮的类名,当前变量对应的小圆点添加类
        const activeClass = document.querySelector(' .slider-indicator .active').classList.remove('active')
      const active = document.querySelector(`.slider-indicator li:nth-child(${i + 1})`).classList.add('active')
      }, 1000)
    })

  </script>
</body>

</html>
焦点事件:小米搜索框
<!DOCTYPE html>
<html lang="en">

<head>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        ul {

            list-style: none;
        }

        .mi {
            position: relative;
            width: 223px;
            margin: 100px auto;
        }

        .mi input {
            width: 223px;
            height: 48px;
            padding: 0 10px;
            font-size: 14px;
            line-height: 48px;
            border: 1px solid #e0e0e0;
            outline: none;
        }

        .mi .search {
            border: 1px solid #ff6700;
        }

        .result-list {
            display: none;
            position: absolute;
            left: 0;
            top: 48px;
            width: 223px;
            border: 1px solid #ff6700;
            border-top: 0;
            background: #fff;
        }

        .result-list a {
            display: block;
            padding: 6px 15px;
            font-size: 12px;
            color: #424242;
            text-decoration: none;
        }

        .result-list a:hover {
            background-color: #eee;
        }
    </style>

</head>

<body>
    <div class="mi">
        <input type="search" placeholder="小米笔记本">
        <ul class="result-list">
            <li><a href="#">全部商品</a></li>
            <li><a href="#">小米11</a></li>
            <li><a href="#">小米10S</a></li>
            <li><a href="#">小米笔记本</a></li>
            <li><a href="#">小米手机</a></li>
            <li><a href="#">黑鲨4</a></li>
            <li><a href="#">空调</a></li>
        </ul>
    </div>
    <script>
        //'[type=search]'是属性选择器
        const input = document.querySelector('[type=search]')
        const ul = document.querySelector('.result-list')
        //获得焦点
        input.addEventListener('focus',function(){
            ul.style.display = 'block'
            input.classList.add('search')
        })
        //失去焦点
        input.addEventListener('blur',function(){
            ul.style.display = 'none'
            input.classList.remove('search')
        })
    </script>
</body>

</html>
键盘事件:评论字数统计

分析:

  1. 判断用户输入事件input
  2. 不断取得文本框里面的字符长度,文本域.value.length
  3. 把获得数字给下面文本框
<!DOCTYPE html>
<html lang="en">

<head>
  <title>评论回车发布</title> 
  <style>
    .wrapper {
      min-width: 400px;
      max-width: 800px;
      display: flex;
      justify-content: flex-end;
    }

    .avatar {
      width: 48px;
      height: 48px;
      border-radius: 50%;
      overflow: hidden;
      background: url(./images/avatar.jpg) no-repeat center / cover;
      margin-right: 20px;
    }

    .wrapper textarea {
      outline: none;
      border-color: transparent;
      resize: none;
      background: #f5f5f5;
      border-radius: 4px;
      flex: 1;
      padding: 10px;
      transition: all 0.5s;
      height: 30px;
    }

    .wrapper textarea:focus {
      border-color: #e4e4e4;
      background: #fff;
      height: 50px;
    }

    .wrapper button {
      background: #00aeec;
      color: #fff;
      border: none;
      border-radius: 4px;
      margin-left: 10px;
      width: 70px;
      cursor: pointer;
    }

    .wrapper .total {
      margin-right: 80px;
      color: #999;
      margin-top: 5px;
      opacity: 0;
      transition: all 0.5s;
    }

    .list {
      min-width: 400px;
      max-width: 800px;
      display: flex;
    }

    .list .item {
      width: 100%;
      display: flex;
    }

    .list .item .info {
      flex: 1;
      border-bottom: 1px dashed #e4e4e4;
      padding-bottom: 10px;
    }

    .list .item p {
      margin: 0;
    }

    .list .item .name {
      color: #FB7299;
      font-size: 14px;
      font-weight: bold;
    }

    .list .item .text {
      color: #333;
      padding: 10px 0;
    }

    .list .item .time {
      color: #999;
      font-size: 12px;
    }
  </style>
</head>

<body>
  <div class="wrapper">
    <i class="avatar"></i>
    <textarea id="tx" placeholder="发一条友善的评论" rows="2" maxlength="200"></textarea>
    <button>发布</button>
  </div>
  <div class="wrapper">
    <span class="total">0/200字</span>
  </div>
  <div class="list">
    <div class="item" style="display: none;">
      <i class="avatar"></i>
      <div class="info">
        <p class="name">清风徐来</p>
        <p class="text">大家都辛苦啦,感谢各位大大的努力,能圆满完成真是太好了[笑哭][支持]</p>
        <p class="time">2022-10-10 20:29:21</p>
      </div>
    </div>
  </div>
<script>
  const tx = document.querySelector('#tx')
  const total = document.querySelector('.total')
//当我们的文本获得焦点,就让total显示出来
  tx.addEventListener('focus',function(){
    total.style.opacity = 1
  })
//当我们的文本失去焦点,就让total隐藏
  tx.addEventListener('blur',function(){
    total.style.opacity = 0
  })
//检测用户输入
  tx.addEventListener('input',function(){
    total.innerHTML = `${tx.value.length}/100`
  })
</script>
</body>

 4.2事件对象

目标:能说出什么是事件对象

事件对象是什么:

也是个对象,这个对象里有事件触发时的关键信息

例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息

使用场景:

可以判断用户按下哪个键,比如按下回车可以发布新闻

可以判断鼠标点击了哪个元素,从而做出响应的操作

语法:如何获取

在事件绑定的回调函数的第一个参数就是事件对象

一般命名为event,ev,e

元素.addEventListener('click',fuction (e) {

})
 事件对象常用属性:
type获取当前的事件类型
clientX / clientY获取光标相对于浏览器可见窗口左上角的位置
offsetX / offsetY获取光标相对于当前DOM元素左上角的位置
key

用户按下的键盘的值

现在不提倡使用keyCode

案例:按下回车键 

<body>
    <input type="text">
    <script>
        const input   = document.querySelector('input')
        input.addEventListener('keyup',function(e){
            if(e.key === 'Enter'){
                console.log('我按下了回车键')
            }
        })
    </script>
</body
案例:评论回车发布

需求:按下回车键,可以发布信息

分析:

用到按下键盘事件keydown或者keyup都可以

如果用户按下的是回车键,则发布信息

让留言信息模块显示,把拿到的数据渲染到对应标签nei

<!DOCTYPE html>
<html lang="en">

<head>
  <style>
    .wrapper {
      min-width: 400px;
      max-width: 800px;
      display: flex;
      justify-content: flex-end;
    }

     .avatar {
      width: 48px;
      height: 48px;
      border-radius: 50%;
      overflow: hidden;
      background: url(./images/avatar.jpg) no-repeat center / cover;
      margin-right: 20px;
    } 

    .wrapper textarea {
      outline: none;
      border-color: transparent;
      resize: none;
      background: #f5f5f5;
      border-radius: 4px;
      flex: 1;
      padding: 10px;
      transition: all 0.5s;
      height: 30px;
    }

    .wrapper textarea:focus {
      border-color: #e4e4e4;
      background: #fff;
      height: 50px;
    }

    .wrapper button {
      background: #00aeec;
      color: #fff;
      border: none;
      border-radius: 4px;
      margin-left: 10px;
      width: 70px;
      cursor: pointer;
    }

    .wrapper .total {
      margin-right: 80px;
      color: #999;
      margin-top: 5px;
      opacity: 0;
      transition: all 0.5s;
    }

    .list {
      min-width: 400px;
      max-width: 800px;
      display: flex;
    }

    .list .item {
      width: 100%;
      display: flex;
    }

    .list .item .info {
      flex: 1;
      border-bottom: 1px dashed #e4e4e4;
      padding-bottom: 10px;
    }

    .list .item p {
      margin: 0;
    }

    .list .item .name {
      color: #FB7299;
      font-size: 14px;
      font-weight: bold;
    }

    .list .item .text {
      color: #333;
      padding: 10px 0;
    }

    .list .item .time {
      color: #999;
      font-size: 12px;
    }
  </style>
</head>

<body>
  <div class="wrapper">
     <i class="avatar"></i> 
    <textarea id="tx" placeholder="发一条友善的评论" rows="2" maxlength="200"></textarea>
    <button>发布</button>
  </div>
  <div class="wrapper">
    <span class="total">0/200字</span>
  </div>
  <div class="list">
    <div class="item" style="display: none;">
      <i class="avatar"></i>
      <div class="info">
        <p class="name">清风徐来</p>
        <p class="text">大家都辛苦啦,感谢各位大大的努力,能圆满完成真是太好了[笑哭][支持]</p>
        <p class="time">2022-10-10 20:29:21</p>
      </div>
    </div>
  </div>
  <script>
    const tx = document.querySelector('#tx')
    const total = document.querySelector('.total')
    const item = document.querySelector('.item')
    const text = document.querySelector('.text')
    tx.addEventListener('focus', function () {
      total.style.opacity = 1
    })
    tx.addEventListener('blur', function () {
      total.style.opacity = 0
    })
    tx.addEventListener('input', function () {
      total.innerHTML = `${tx.value.length}/100`
    })
    tx.addEventListener('keyup', function (e) {
      if (e.key === 'Enter') {
        //如果用户输入的不为空就显示和打印
        if (tx.value.trim()) {
          item.style.display = 'block'
          //用户输入的内容
          text.innerHTML = tx.value
        }
        //按下回车清空文本域
        tx.value = ''
        total.innerHTML = '0/200字'
      }
    })
  </script>
</body>

</html>

4.3环境对象

目标:能够分析判断函数运行在不同环境中this所指代的对象

环境对象:指的是函数内部特殊的变量this,它代表着当前函数运行时所处的环境

作用:弄清楚this的指向,可以让我们代码更简洁

  • 函数的调用方式不同,this指代的对象也不同
  • 【谁调用,this就是谁】是判断this指向的粗略规则
  • 直接调用函数,其实相当于是window函数,所以this指代window
<body>
    <button>点击</button>
    <script>
        const btn = document.querySelector('button')
        btn.addEventListener('click',function(){
            console.log(this) //btn对象
            this.style.color = 'red'
        })
    </script>
</body>

4.4回调函数

目标:能够说出什么是回调函数

如果将函数A作为参数传递给函数B时,我们称函数A为回调函数

简单理解:当一个函数当作参数来传递给另外一个函数的时候,这个函数就是回调函数

<body>
    <button>点击</button>
    <script>
        function fn() {
            console.log('我是回调函数')
        }
        //fn传递给了setInterval,fn就是回调函数
        setInterval(fn, 1000)
    </script>
</body>
案例:tab栏切换
<!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>tab栏切换</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .tab {
      width: 590px;
      height: 340px;
      margin: 20px;
      border: 1px solid #e4e4e4;
    }

    .tab-nav {
      width: 100%;
      height: 60px;
      line-height: 60px;
      display: flex;
      justify-content: space-between;
    }

    .tab-nav h3 {
      font-size: 24px;
      font-weight: normal;
      margin-left: 20px;
    }

    .tab-nav ul {
      list-style: none;
      display: flex;
      justify-content: flex-end;
    }

    .tab-nav ul li {
      margin: 0 20px;
      font-size: 14px;
    }

    .tab-nav ul li a {
      text-decoration: none;
      border-bottom: 2px solid transparent;
      color: #333;
    }

    .tab-nav ul li a.active {
      border-color: #e1251b;
      color: #e1251b;
    }

    .tab-content {
      padding: 0 16px;
    }

    .tab-content .item {
      display: none;
    }

    .tab-content .item.active {
      display: block;
    }
  </style>
</head>

<body>
  <div class="tab">
    <div class="tab-nav">
      <h3>每日特价</h3>
      <ul>
        <li><a class="active" href="javascript:;">精选</a></li>
        <li><a href="javascript:;">美食</a></li>
        <li><a href="javascript:;">百货</a></li>
        <li><a href="javascript:;">个护</a></li>
        <li><a href="javascript:;">预告</a></li>
      </ul>
    </div>
    <div class="tab-content">
      <div class="item active"><img src="./tab00.png" alt="" /></div>
      <div class="item"><img src="./tab01.png" alt="" /></div>
      <div class="item"><img src="./tab02.png" alt="" /></div>
      <div class="item"><img src="./tab03.png" alt="" /></div>
      <div class="item"><img src="./tab04.png" alt="" /></div>
    </div>
  </div>
  <script>
    const a = document.querySelectorAll('.tab-nav a')
    //遍历每一个
    for (let i = 0; i < a.length; i++) {

      //添加鼠标经过事件
      a[i].addEventListener('mouseenter', function () {
        //排它思想,先移除后添加
        document.querySelector('.tab-nav .active').classList.remove('active')
        // a[i].classList.add('active')
        this.classList.add('active')

      //下面五个大盒子一一对应 .item
        //排它思想
        document.querySelector('.tab-content .active').classList.remove('active')
        document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')
      })
    }
  </script>
</body>

</html>

全选文本框案例1 :

需求:用户点击全选,则下面复选框全部选择,取消全选则全部取消

分析:

  • 全选复选框点击,可以得到当前按钮的 checked
  • 把下面所有的小复选框状态checked,改为和全选复选框一致  

  • 遍历下面的所有的checked,添加点击事件
  • 检查小复选框选中的个数,是不是等于小复选框总的个数
  • 把结果给 全选按钮
  • 利用css 复选框选择器 input:checked
<!DOCTYPE html>
<html lang="en">

<head>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    table {
      border-collapse: collapse;
      border-spacing: 0;
      border: 1px solid #c0c0c0;
      width: 500px;
      margin: 100px auto;
      text-align: center;
    }

    th {
      background-color: #09c;
      font: bold 16px "微软雅黑";
      color: #fff;
      height: 24px;
    }

    td {
      border: 1px solid #d0d0d0;
      color: #404060;
      padding: 10px;
    }

    .allCheck {
      width: 80px;
    }
  </style>
</head>

<body>
  <table>
    <tr>
      <th class="allCheck">
        <input type="checkbox" name="" id="checkAll"> <span class="all">全选</span>
      </th>
      <th>商品</th>
      <th>商家</th>
      <th>价格</th>
    </tr>
    <tr>
      <td>
        <input type="checkbox" name="check" class="ck">
      </td>
      <td>小米手机</td>
      <td>小米</td>
      <td>¥1999</td>
    </tr>
    <tr>
      <td>
        <input type="checkbox" name="check" class="ck">
      </td>
      <td>小米净水器</td>
      <td>小米</td>
      <td>¥4999</td>
    </tr>
    <tr>
      <td>
        <input type="checkbox" name="check" class="ck">
      </td>
      <td>小米电视</td>
      <td>小米</td>
      <td>¥5999</td>
    </tr>
  </table>
  <script>
 //获取大复选框
    const checkAll = document.querySelector('#checkAll')
    //获取所有的小复选框
    const cks = document.querySelectorAll('.ck')
    //点击大复选框,注册事件
    checkAll.addEventListener('click', function () {
      //得到当前大复选框的选中状态
      //console.log(checkAll.checked) //是false 或者 true
      //遍历所有的小复选框,让小复选框的checked = 大复选框的checked
      for (let i = 0; i < cks.length; i++) {
        cks[i].checked = checkAll.checked
      }
    })

    //小复选框控制大复选框
    for (let i = 0; i < cks.length; i++) {
      cks[i].addEventListener('click',function(){
        //判断选中的小复选框的个数 是不是等于 总的小复选框个数
        //一定要写到点击里面,因为每次要获得最新的个数
        console.log(document.querySelectorAll('.ck:checked').length) //小复选框被选中的个数
        console.log(document.querySelectorAll('.ck:checked').length === cks.length) //选中的小复选框个数是否等于总复选框个数,返回的是true或者false
        checkAll.checked = document.querySelectorAll('.ck:checked').length === cks.length

      })
    }
  </script>
</body>

</html>

5.事件流

5.1事件流和两个阶段说明

事件流指的是事件完整执行过程中的流动路径

  • 说明:假设页面里面有个div,当触发事件时,会经历两个阶段,分别是捕获阶段,冒泡阶段
  • 简单来说:捕获阶段是 从父到子 冒泡阶段是从子到父
  • 实际工作都是使用事件冒泡为主

5.2事件捕获

事件捕获概念:

  • 从DOM的根元素开始去执行对应的事件(从外到里)
  • 事件捕获需要写对应代码才能看到效果

代码:

DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)

说明:

addEventListener第三个参数传入true代表的是捕获阶段触发(很少使用)

若传入false代表冒泡阶段触发,默认就是false       

若是用L0事件监听,则只有冒泡阶段,没有捕获

<!DOCTYPE html>
<html lang="en">

<head>
  <style>
    .father{
      width: 200px;
      height: 200px;
      background-color:palegoldenrod;
    }
    .son{
      width: 100px;
      height: 100px;
      background-color:plum;
    }
  </style>
</head>

<body>
  <div class="father">
    <div class="son"></div>
  </div>
  <script>
    const fa = document.querySelector('.father')
    const son = document.querySelector('.son')
    document.addEventListener('click', function () {
      alert('我是爷爷')
    }, true)
    fa.addEventListener('click', function () {
      alert('我是爸爸')
    }, true)
    son.addEventListener('click', function () {
      alert('我是儿子')
    }, true)
  </script>
</body>

</html>

5.3事件冒泡

事件冒泡概念:

一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡 

  • 简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件
  • 事件冒泡是默认存在的
  • L2事件监听第三个参数是false,或者默认都是冒泡
<!DOCTYPE html>
<html lang="en">

<head>
  <style>
    .father{
      width: 200px;
      height: 200px;
      background-color:palegoldenrod;
    }
    .son{
      width: 100px;
      height: 100px;
      background-color:plum;
    }
  </style>
</head>

<body>
  <div class="father">
    <div class="son"></div>
  </div>
  <script>
    const fa = document.querySelector('.father')
    const son = document.querySelector('.son')
    document.addEventListener('click', function () {
      alert('我是爷爷')
    })
    fa.addEventListener('click', function () {
      alert('我是爸爸')
    })
    son.addEventListener('click', function () {
      alert('我是儿子')
    })
  </script>
</body>

</html>

5.4阻止冒泡

问题:因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素

需求:若想把事件就限制在当前元素内,就需要阻止事件冒泡

前提:阻止事件冒泡需要拿到事件对象

语法:

事件对象.stopPropagation()

注意:此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效

<!DOCTYPE html>
<html lang="en">

<head>
  <style>
    .father{
      width: 200px;
      height: 200px;
      background-color:palegoldenrod;
    }
    .son{
      width: 100px;
      height: 100px;
      background-color:plum;
    }
  </style>
</head>

<body>
  <div class="father">
    <div class="son"></div>
  </div>
  <script>
    const fa = document.querySelector('.father')
    const son = document.querySelector('.son')
    document.addEventListener('click', function () {
      alert('我是爷爷')
    })
    fa.addEventListener('click', function () {
      alert('我是爸爸')
    })
    son.addEventListener('click', function (e) {
      alert('我是儿子')
      //阻止流动传播
      e.stopPropagation()
    })
  </script>
</body>

</html>

5.5阻止默认行为

我们某些情况下需要阻止默认行为的发生,比如 阻止 链接的跳转,表单域跳转

语法:

e.preventDefault( )

案例:

<body>
  <form action="http://www.itcast.cn">
    <input type="submit" value="免费注册">
  </form>
  <a href="http://www.baidu.com"></a>
  <script>
    const form = document.querySelector('form')
    form.addEventListener('submit', function (e) {
      //阻止默认行为 提交
      //在某些情况下没有满足提交条件时需要阻止默认行为
      e.preventDefault()
    })
    const a = document.querySelector('a')
    a.addEventListener('click', function (e) {
      e.preventDefault()
    })
  </script>
</body>

5.6事件解绑

on事件方式,直接使用null覆盖就可以实现事件解绑

//绑定事件
btn.onclick = function() {
    alert('点击了')
}
//解绑事件
btn.onclick = null

addEventListener方式,必须使用:

removeEventListener(事件类型,事件处理函数,【获取捕获或者冒泡阶段】)

注意:匿名函数无法被解绑

function fn() {
    alert('点击了')
}
//绑定事件
btn.addEventListener('click',fn)
//解绑事件
btn.removeEventListener('click',fn)

5.7鼠标经过事件的区别:

鼠标经过事件:

  • mouseover和mouseout会有冒泡效果
  • mouseenter和mouseleave没有冒泡效果(推荐)

传统on注册(L0):

  • 同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
  • 直接使用null覆盖就可以实现事件解绑
  • 都是冒泡阶段执行的

事件监听注册(L2):

  • 语法:addEventListener(事件类型,事件处理函数,是否使用捕获)
  • 后面注册的事件不会覆盖前面注册的事件(同一个事件)
  • 可以通过第三个参数去确定是在冒泡阶段或者捕获阶段执行
  • 必须使用removeEventListener(事件类型,事件处理函数,获取捕获或者冒泡阶段)
  • 匿名函数无法被解绑

6.事件委托

事件委托是利用事件流的特征解决一些开发需求的知识技巧
优点:减少注册次数,可以提高程序性能
原理:事件委托其实是利用事件冒泡的特点

给父元素注册事件,当我们触发子元素的时候,就会冒泡到父元素身上,从而触发父元素的事件

实现:事件对象.target.tagName可以获得真正触发事件的元素

<body>
  <ul>
    <li>我是第1个li标签</li>
    <li>我是第2个li标签</li>
    <li>我是第3个li标签</li>
    <li>我是第4个li标签</li>
    <li>我是第5个li标签</li>
    <p>这是p标签</p>
  </ul>
  <script>
    //点击每一个小li 当前li 文字变为红色
    //按照事件委托的方式 委托给父级 事件写到父级上
    //1.获得父元素
    const ul = document.querySelector('ul')
    ul.addEventListener('click', function (e) {
      //console.log(e.target)  点击的那个对象
      //我们的需求,只需要点击li才会有效果
      if (e.target.tagName === 'LI') {
        e.target.style.color = 'red'
      }
    })
  </script>
</body>
案例:tab栏切换-事件委托版
//css样式不变

<body>
  <div class="tab">
    <div class="tab-nav">
      <h3>每日特价</h3>
      <ul>
        <li><a class="active" href="javascript:;" data-id="0">精选</a></li>
        <li><a href="javascript:;" data-id="1">美食</a></li>
        <li><a href="javascript:;" data-id="2">百货</a></li>
        <li><a href="javascript:;" data-id="3">个护</a></li>
        <li><a href="javascript:;" data-id="4">预告</a></li>
      </ul>
    </div>
    <div class="tab-content">
      <div class="item active"><img src="./tab00.png" alt="" /></div>
      <div class="item"><img src="./tab01.png" alt="" /></div>
      <div class="item"><img src="./tab02.png" alt="" /></div>
      <div class="item"><img src="./tab03.png" alt="" /></div>
      <div class="item"><img src="./tab04.png" alt="" /></div>
    </div>
  </div>
  <script>
    //使用事件委托
    //1.获得父元素
    const ul = document.querySelector('ul')
    //2.添加点击事件
    ul.addEventListener('click', function (e) {
      //e.target是我们点击的对象
      console.log(e.target)
      //只有当点击a标签时才会生效
      if (e.target.tagName === 'A') {
        //排它思想 先移除原来的active
        document.querySelector('.tab-nav .active').classList.remove('active')
        //this指向ul 不能用this
        e.target.classList.add('active')

        //大盒子模块
        //因为data-id="0"采用的是字符串类型,需要转换为数字类型
        const i = +e.target.dataset.id
        document.querySelector('.tab-content .active').classList.remove('active')
        document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')
      }

    })
  </script>
</body>
知识点补充—css自定义属性:
<body>
  <div data-id="0"></div>
  <script>
    const div = document.querySelector('div')
    console.log(div.dataset.id) //0
  </script>
</body>

7.其他事件

7.1页面加载事件

Load事件:

加载外部资源(如图片,外联css和javscript等)加载完毕时触发的事件
为什么要学?

  • 有些时候需要等待页面资源全部处理完了做一些事情
  • 老代码喜欢把script写在head中,这时候直接找dom元素找不到

事件名:load
监听页面所有资源加载完毕:
        给window添加load事件

<head>
<script>
  //等待页面所有资源加载完毕,就回去执行回调函数
  window.addEventListener('load',function(){
    const btn = document.querySelector('button')
    btn.addEventListener('click',function(){
      alert(11)
    })
  })
  img.addEventListener('load',function(){
    //等待图片加载完毕,再去执行里面的代码
  })
</script>
</head>

<body>
<button>点击</button>
</body>

</html>

注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定load事件

DOMContentLoaded事件:

当初始的HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表,图像等完全加载
事件名:DOMContentLoaded

事件页面DOM加载完毕: 

  • 给document添加DOMContentLoaded事件
  document.addEventListener('DOMContentLoaded',function(){
    const btn = document.querySelector('button')
    btn.addEventListener('click',function(){
      alert(11)
    })
  })

页面加载事件有哪两个?如何添加?

load事件:监听整个页面资源给Window加

DOMContentLoaded事件:给document加,无需等待样式表,图像等完全加载

7.2元素滚动事件

滚动条在滚动的时候持续触发的事件
为什么要学?
很多页面需要检测用户把页面滚动到某个区域后做一些处理,比如固定导航栏,比如返回顶部
事件名:scroll
监听整个页面滚动:

//页面滚动事件
window.addEventListener('scroll',function(){
    //执行的操作
})
  • 给window或document添加scroll事件 
  • 监听某个元素的内部滚动直接给某个元素添加即可
获取位置-scrollLeft和scrollTop(属性):
  • 获取被卷去的大小
  • 获取元素内容往左,往上滚出去看不到的距离
  • 这两个值是可读写的
<head>
  <style>
    body {
      padding-top: 100px;
      height: 3000px;
    }

    div {
      margin: 100px;
      overflow: scroll;
      width: 200px;
      height: 200px;
      border: 1px solid #000
    }
  </style>
</head>

<body>
  <div>
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字 
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
  </div>
  <script>
    const div = document.querySelector('div')
    div.addEventListener('scroll', function () {
      //通过div.scrollTop知道div内滚动了多少
      console.log(div.scrollTop)
      //获取html元素写法,通过document.documentElement.scrollTop知道页面到底滚动了多少
      console.log(document.documentElement.scrollTop)
    })
  </script>
</body>

</html>

在HTML页面中滚动100px后出现div,往回滚动小于100px时div消失:

<head>
  <style>
    body {
      padding-top: 100px;
      height: 3000px;
    }

    div {
      display: none;
      margin: 100px;
      overflow: scroll;
      width: 200px;
      height: 200px;
      border: 1px solid #000
    }
  </style>
</head>

<body>
  <div>
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字 
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
    我里面有很多文字
  </div>
  <script>
    const div = document.querySelector('div')
    window.addEventListener('scroll', function () {
      //当HTML页面滚动了100px时出现div
      const n = document.documentElement.scrollTop
      if (n >= 100) {
        div.style.display = 'block'
      } else {
        div.style.display = 'none'
      }
    })
  </script>
</body>
滚动到指定的坐标-scrollTo()

scrollTo()方法可把内容滚动到指定的坐标

语法:

元素.scrollTo(x,y)
//让页面滚动到y轴1000像素的位置
window.scrollTo(0,1000)
 电梯导航案例:
  <!-- 电梯 -->
  <div class="xtx-elevator">
    <ul class="xtx-elevator-list">
      <li><a href="javascript:;" data-name="new">新鲜好物</a></li>
      <li><a href="javascript:;" data-name="popular">人气推荐</a></li>
      <li><a href="javascript:;" data-name="brand">热门品牌</a></li>
      <li><a href="javascript:;" data-name="topic">最新专题</a></li>
      <li><a href="javascript:;" id="backTop"><i class="sprites"></i>顶部</a></li>
    </ul>
  </div>
  <script>
    const elevator = document.querySelector('.xtx-elevator')
    window.addEventListener('scroll', function () {
      const n = document.documentElement.scrollTop
      // if (n >= 300) {
      //   elevator.style.opacity = 1
      // } else {
      //   elevator.style.opacity = 0
      // }
      elevator.style.opacity = n >= 300 ? 1 : 0
    })
    //点击返回页面顶部
    const backTop = document.querySelector('#backTop')
    backTop.addEventListener('click',function(){
      //可读写
      // document.querySelectorAll.scrollTop = 0
      // window.scrollTo(x,y)
      window.scrollTo(0,0)
    })
  </script>

7.3页面尺寸事件

获取元素宽高:
  • 获取元素的可见部分宽高(不包含边框,margin,滚动条等)
  • clientWidth和clientHeight

会在窗口尺寸改变的时候触发事件:

  • resize
window.addEventListener('resize',function(){})

检测屏幕宽度:

window.addEventListener('resize',function(){
    let w = document.documentElement.clientWidth
    console.log(w)
}) 
元素尺寸于位置:

使用场景:

  • 前面案例滚动多少距离,都是我们自己算的,最好是页面滚动到某个元素,就可以做某些事
  • 简单说,就是通过js的方式,得到元素在页面中的位置
  • 这样我们可以做,页面滚动到这个位置,就可以做某些操作,省去计算了
 元素尺寸于位置-尺寸
获取宽高:
  • 获取元素的自身高度,包括元素自身设置的宽高,padding,border

  • offsetWidth和offsetHeight

  • 获取出来的是数值,方便计算

  • 注意:获取的是可视宽高,如果盒子是隐藏的,获取到的结果是0

获取位置:

  • 获取元素距离自己定位父级元素的左,上距离

  • offsetLeft和offsetTop注意是只读属性

<!DOCTYPE html>
<html lang="en">

<head>
  <style>
    div {
      position: relative;
      width: 200px;
      height: 200px;
      background-color: pink;
      margin: 100px;
    }
    p{
      width: 100px;
      height: 100px;
      background-color: purple;
      margin: 50px;
    }
  </style>
</head>

<body>
<div>
  <p></p>
</div>
  <script>
const div = document.querySelector('div')
const p = document.querySelector('p')
//检测盒子的位置 最近一级带有定位的祖先元素
console.log(p.offsetLeft)
  </script>
</body>

</html>

 offsetWidth和offsetHeight是得到元素什么高度?

  • 内容+padding+border

offsetTop和offsetLeft得到的位置以谁为准?

  • 带有定位的父级
  • 如果都没用则以文档左上角
仿东京固定导航栏案例

 需求:当页面滚动到秒杀模块,导航栏自动滑入,否则滑出

 分析:

  • 用到页面滚动事件
  • 检测页面滚动大于等于秒杀模块的位置则滑入,否则滑出
  • 主要移动的是秒杀模块的顶部位置
<head>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .content {
            overflow: hidden;
            width: 1000px;
            height: 3000px;
            background-color: pink;
            margin: 0 auto;
        }

        .backtop {
            display: none;
            width: 50px;
            left: 50%;
            margin: 0 0 0 505px;
            position: fixed;
            bottom: 60px;
            z-index: 100;
        }

        .backtop a {
            height: 50px;
            width: 50px;
            background: url(./images/bg2.png) 0 -600px no-repeat;
            opacity: 0.35;
            overflow: hidden;
            display: block;
            text-indent: -999em;
            cursor: pointer;
        }

        .header {
            position: fixed;
            top: -80px;
            left: 0;
            width: 100%;
            height: 80px;
            background-color: purple;
            text-align: center;
            color: #fff;
            line-height: 80px;
            font-size: 30px;
            transition: all .3s;
        }

        .sk {
            width: 300px;
            height: 300px;
            background-color: skyblue;
            margin-top: 500px;
        }
    </style>
</head>

<body>
    <div class="header">我是顶部导航栏</div>
    <div class="content">
        <div class="sk">秒杀模块</div>
    </div>
    <div class="backtop">
        <img src="./images/close2.png" alt="">
        <a href="javascript:;"></a>
    </div>
    <script>
        const sk = document.querySelector('.sk')
        const header = document.querySelector('.header')
        window.addEventListener('scroll', function () {
            //当页面滚动到 秒杀模块的时候,就改变头部的top值
            //页面被卷去的头部 >= 秒杀模块的位置 offsetTop
            const n = document.documentElement.scrollTop
            // if (n >= sk.offsetTop) {
            //     header.style.top = 0
            // }else{
            //     header.style.top = '-80px'
            // }
            header.style.top = n >= sk.offsetTop ? 0 : '-80px'
        })
    </script>
</body>

</html>
实现bilibili点击小滑块移动效果

需求:当点击链接,下面红色滑块跟着移动
分析:

  • 用到事件委托
  • 点击链接得到当前元素的offsetLeft值
  • 修改line颜色块的transform值 = 点击链接的offsetLeft
  • 添加过渡效果
  <script>
    const list = document.querySelector('.tabs-list')
    const line = document.querySelector('.line')
    list.addEventListener('click', function (e) {
      if (e.target.tarName = 'A') {
        // console.log(11)
        // console.log((e.target.offsetLeft - 16) / 3.75 + 'vw')
        // console.log((e.target.offsetLeft) / 3.75 + 'vw')
        line.style.left = (e.target.offsetLeft + 16) / 3.75 + 'vw'
      }
    })
  </script>
元素尺寸于位置-尺寸 获取位置:
element.getBoundingClientRect()

方法返回元素的大小及其相对于视口的位置 

总结:

8.日期对象 

8.1实例化

目标:能够实例化日期对象

  • 在代码中发现了neW关键字时,一般将这个操作称为实例化
  • 创建一个时间对象并获取时间

获得当前时间:

const date = new Date()

获得指定时间:

const date = new Date('2008-8-8')
console.log(date)

8.2时间对象方法

目标:能够使用日期对象中的方法写出常见日期
使用场景:因为日期对象返回的数据我们不能直接使用,所以需要转换为实际开发中常用的格式

//获得日期对象
const date = new Date()
//使用里面的方法
console.log(date.getFullYear())
console.log(date.getMonth()+1) //需要+1
console.log(date.getDate())
console.log(date.getDay())/星期几
案例-页面显示时间

需求:将当前时间以:YYYY-MM-DD HH:mm形式显示在页面2008-08-08 08:08
分析:
①:调用日期对象方法进行转换
②:记得数字要补0

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
</head>

<body>
    <div></div>

    <script>
        const div = document.querySelector('div')
        function getMyDate() {
            const date = new Date()
            //判断是否大于10
            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 = getMyDate()
        //定时器,页面的时间戳可以随之变化
        setInterval(function () {
            //div中的文字返回的是getMyDate()的结果
            div.innerHTML = getMyDate()
        }, 1000)
    </script>
</body>

</html>

另一种写法:

<body>
    <div></div>

    <script>
        const div = document.querySelector('div')
        const date = new Date()
        div.innerHTML = date.toLocaleString()
    </script>
</body>

</html>

2023/10/4 17:46:49

8.3时间戳

目标:能够获得当前时间戳
使用场景:如果计算倒计时效果,前面方法无法直接计算,需要借助于时间戳完成(因为年月日无法直接相加减,所以使用时间戳)
什么是时间戳:

  • 是指1970年01月01日00时00分00秒起至现在的毫秒数,它是一种特殊的计量时间的方式

算法:

  • 将来的时间戳-现在的时间戳=剩余时间毫秒数
  • 剩余时间毫秒数 转换为 剩余时间的年月日时分秒就是倒计时时间
  • 比如,将来时间戳2000ms-现在时间戳1000ms=1000ms
  • 1000m5转换为就是0小时0分1秒
 三种方式获取时间戳:

1.使用getTime()方法——必须需实例化

const date = new Date()
console.log(date.getTime())

2.简写+new Date()——无需实例化

console.log(+new Date())

3.使用Date.now()——无需实例化

但是只能得到当前的时间戳,而前面两种可以返回指定的时间戳

console.log(Date.now())

获取指定时间戳:

console.log(+new Date('2023-4-1 23:10:00'))

根据日期Day() 0~6 返回的是星期一:

    <script>
        //根据日期Day() 0~6 返回的是星期一
        const arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
        console.log(arr[new Date().getDay()])
    </script>

9.节点操作

9.1DOM节点

目标:能说出DOM节点的类型
DOM节点:
DOM树里每一个内容都称之为节点

节点类型:
 元素节点

  • 所有的标签比如body、div
  • html是根节点

  属性节点

  • 所有的属性比如href

 文本节点

  • 所有的文本

  其他

9.2查找节点

目标:能够具备根据节点关系查找目标节点的能力
关闭二维码案例:
点击关闭按钮,关闭的是二维码的盒子,还要获取erweima盒子


思考:

  • 关闭按钮和erweima是什么关系呢?
  • 父子关系
  • 所以,我们完全可以这样做:
  • 点击关闭按钮,直接关闭它的爸爸,就无需获取erweima元素了

节点关系:针对的找亲戚返回的都是对象

  • 父节点
  • 子节点
  • 兄弟节点 
 父节点查找:

parentNode属性
返回最近一级的父节点 找不到返回null

<body>
    <div class="grandfeather">
        <div class="feather">
            <div class="baby"></div>
        </div>
    </div>

    <script>
        const baby = document.querySelector('.baby')
        //子节点
        console.log(baby)
        //父节点
        console.log(baby.parentNode)
        //父节点的父节点
        console.log(baby.parentNode.parentNode)
    </script>
</body>
点击关闭广告案例:
<head>
    <style>
      .box {
        position: relative;
        width: 1000px;
        height: 200px;
        background-color: pink;
        margin: 100px auto;
        text-align: center;
        font-size: 50px;
        line-height: 200px;
        font-weight: 700;
      }
  
      .box1 {
        position: absolute;
        right: 20px;
        top: 10px;
        width: 20px;
        height: 20px;
        background-color: skyblue;
        text-align: center;
        line-height: 20px;
        font-size: 16px;
        cursor: pointer;
      }
    </style>
  </head>
  
  <body>
    <div class="box">
      我是广告
      <div class="box1">X</div>
    </div>
    <script>
      // 1. 获取事件源
      const box1 = document.querySelector('.box1')
      // 2. 事件侦听
      box1.addEventListener('click', function () {
        this.parentNode.style.display = 'none'
      })
    </script>
  </body>
  
  

多个广告窗口-点击哪个关闭哪个:

<body>
    <div class="box">
        我是广告
        <div class="box1">X</div>
    </div>
    <div class="box">
        我是广告
        <div class="box1">X</div>
    </div>
    <div class="box">
        我是广告
        <div class="box1">X</div>
    </div>
    <script>
        //注册事件,多个关闭按钮,点击谁谁关闭
        const closeBtn = document.querySelectorAll('.box1')
        for (let i = 0; i < closeBtn.length; i++) {
            closeBtn[i].addEventListener('click', function () {
                this.parentNode.style.display = 'none'
            })
        }
    </script>
</body>
子节点查找:

childNodes

  • 获得所有子节点、包括文本节点(空格、换行)、注释节点等

children属性(重点)

  • 仅获得所有元素节点
  • 返回的还是一个伪数组
<body>
    <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
    <script>
        const ul = document.querySelector('ul')
        console.log(ul.children) //得到伪数组 选择的是亲儿子
    </script>
</body>
 兄弟关系查找:

1.下一个兄弟节点

  • nextElementSibling属性

2.上一个兄弟节点

  • previousElementSibling属性
<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script>
        const li2 = document.querySelector('ul li:nth-child(2)')
        console.log(li2.nextElementSibling) //下一个兄弟节点
        console.log(li2.previousElementSibling)//上一个兄弟节点
    </script>
</body>

9.3增加节点

目标:能够具备根据需求新增节点的能力
很多情况下,我们需要在页面中增加元素

  • 比如,点击发布按钮,可以新增一条信息

一般情况下,我们新增节点,按照如下操作:

  • 创建一个新的节点
  • 把创建的新的节点放入到指定的元素内部

学习路线:

  • 创建节点
  • 追加节点
 创建节点:

即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点
创建元素节点方法:

//创建一个新的元素节点
document.createElement('标签名')
追加节点:

要想在界面看到,还得插入到某个父元素中
插入到父元素的最后一个子元素:

//插入到这个父元素的最后
父元素.appendChild(要插入的元素)

插入到父元素中某个子元素的前面:

//插入到某个子元素的前面
父元素.insertBefore(要插入的元素,在哪个元素前面)
案例:
<body>
    <ul>
        <li>我是老大</li>
    </ul>
    <script>

        const ul = document.querySelector('ul')
        //创建节点 li
        const li = document.createElement('li')
        li.innerHTML = '我是li'
        //追加节点 作为最后一个元素
        ul.appendChild(li)

        //插入到父元素中某个子元素的前面
        //创建节点 li
        const li2 = document.createElement('li')
        li2.innerHTML = '我是li2'
        //ul.childern = ul中的子节点 >>> ul.childern[0] = ul中的第一个子节点
        ul.insertBefore(li2, ul.children[0])
    </script>
</body>
学成在线案例渲染:

需求:按照数据渲染页面
分析:

  • 准备好空的ul结构
  • 根据数据的个数,创建一个新的空li
  • li里面添加内容img标题等
  • 追加给ul
<!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>
    <link rel="stylesheet" href="./css/style.css">
    <style>

    </style>
</head>

<body>

    <!-- 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>
        // 1. 重构  
        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
            },
        ]
        const ul = document.querySelector('.box-bd ul')
        // 1. 根据数据的个数,创建 对应的小li
        for (let i = 0; i < data.length; i++) {
            // 2. 创建新的小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>
            `
            // 3. ul追加小li
            ul.appendChild(li)
        }
    </script>
</body>

</html>

克隆节点:

特殊情况下,我们新增节点,按照如下操作:

  • 复制一个原有的节点
  • 把复制的节点放入到指定的元素内部
//克隆一个已有的元素节点
元素.cloneNode(布尔值)

cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值:

  • 若为true,则代表克隆时会包含后代节点一起克隆
  • 若为false,则代表克隆时不包含后代节点
  • 默认为false

<body>
    <ul>
        <li>我是老1</li>
        <li>我是老2</li>
        <li>我是老3</li>
        <li>我是老4</li>
    </ul>
    <script>
        const ul = document.querySelector('ul')
        //1.克隆节点 元素.cloneNode(true)
        const li1 = ul.children[0].cloneNode(true)
        //2.追加
        // ul.appendChild(li1)
        ul.appendChild(ul.children[0].cloneNode(true)) //深拷贝
        ul.appendChild(ul.children[0].cloneNode())//浅拷贝
    </script>
</bo

9.4删除节点

目标:能够具备根据需求删除节点的能力
若一个节点在页面中已不需要时,可以删除它
在JavaScript原生DOM操作中,要删除元素必须通过父元素删除
语法:

父元素.removeChild(要删除的元素)

注:

  • 如不存在父子关系则删除不成功
  • 删除节点和隐藏节点(display:none)有区别的:隐藏节点还是存在的,但是删除,则从html中删除节点
<body>
    <ul>
        <li>我是老1</li>
        <li>我是老2</li>
        <li>我是老3</li>
        <li>我是老4</li>
    </ul>
    <script>
        const ul = document.querySelector('ul')
        //删除节点 父元素.removeChlid(子元素)
        ul.removeChild(ul.children[0])
    </script>
</body>

 10.M端事件

目标:了解M端常见的事件
移动端也有自己独特的地方。比如触屏事件touch(也称触摸事件),Android和IOS都有。

  • 触屏事件touch(也称触摸事件),Android和IOS都有。
  • touch对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触屏事件可响应用户手指(或触控笔
  • )对屏幕或者触控板操作。

常见的触屏事件如下:

触屏touch事件说明
touchstart手指触摸到一个DOM元素时触发
touchmove手指在一个DOM元素上滑动时触发
touchend手指从一个DOM元素上移开时触发
<!DOCTYPE html>
<html lang="en">

<head>
  <style>
    div {
      position: relative;
      width: 200px;
      height: 200px;
      background-color: pink;
      margin: 100px;
    }
  </style>
</head>

<body>
  <div></div>
  <script>
    const div = document.querySelector('div')
    //1.触摸
    div.addEventListener('touchstart', function () {
      console.log('开始摸我了')
    })
    //2.离开
    div.addEventListener('touchend', function () {
      console.log('离开了')
    })
    //3.移动
    div.addEventListener('touchmove', function () {
      console.log('一直摸,移动')
    })
  </script>
</body>

</html>

11.swiper插件--第124p

插件:就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果
学习插件的基本过程
熟悉官网,了解这个插件可以完成什么需求
https://www.swiper.com.cn/
看在线演示,找到符合自己需求的demo
https://www.swiper.com.cn/demo/index.html
查看基本使用流程
https://www.swiper.com.cn/usage/index.html
查看APi文档,去配置自己的插件  https://www.swiper.com.cn/api/index.html
注意:多个swiperl同时使用的时候,类名需要注意区分

12.Window对象

12.1BOM(浏览器对象模型)

  • BOM(Browser Object Model)是浏览器对象模型

  • window对象是一个全局对象,也可以说是JavaScript中的顶级对象
  • 像document、alert()、console..log()这些都是window的属性,基本BOM的属性和方法都是window的。
  • 所有通过var定义在全局作用域中的变量、函数都会变成window对象的属性和方法
  • window对象下的属性和方法调用的时候可以省略window
     

12.2定时器-延时函数

JavaScript内置的一个用来让代码延迟执行的函数,叫setTimeout
语法:

setTimeout(回调函数,等待的毫秒数)

setTimeout仅仅只执行一次,所以可以理解为就是把一段代码延迟执行,平时省略window
清除延时函数:

let timer=setTimeout(回调函数,等待的毫秒数)
clearTimeout(timer)

注意点:
延时器需要等待,所以后面的代码先执行
每一次调用延时器都会产生一个新的延时器

两种定时器对比:执行的次数
延时函数:执行一次
间歇函数:每隔一段时间就执行一次,除非手动清除

5秒钟之后消失的广告:

需求:5秒钟之后,广告自动消失
分析:
①:设置延时函数
②:隐藏元素

<head>
    <style>
        .box {
            position: relative;
            width: 1000px;
            height: 200px;
            background-color: pink;
            margin: 100px auto;
            text-align: center;
            font-size: 50px;
            line-height: 200px;
            font-weight: 700;
        }

        .box1 {
            position: absolute;
            right: 20px;
            top: 10px;
            width: 20px;
            height: 20px;
            background-color: skyblue;
            text-align: center;
            line-height: 20px;
            font-size: 16px;
            cursor: pointer;
        }
    </style>
</head>

<body>
    <div class="box">
        关闭广告
        <div class="box1">X</div>
    </div>
    <script>
        const div1 = document.querySelector('.box1')
        setTimeout(function () {
            div1.parentNode.style.display = 'none'
        }, 5000)
    </script>
</body>

12.3JS执行机制

JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。

  • 这是因为Javascript这门脚本语言诞生的使命所致一JavaScript是为处理页面中用户的交互,以及操作DOM而诞生的。比如我们对某个DOM元素进行添加和删除操作,不能同时进行。应该先进行添加,之后再删除。
  • 单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是:如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
  • JS执行机制
  • 为了解决这个问题,利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程。于是,JS中出现了同步和异步。

同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。
异步
你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事
情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。
他们的本质区别:这条流水线上各个流程的执行顺序不同。

同步任务
同步任务都在主线程上执行,形成一个执行栈。
异步任务
JS的异步是通过回调函数实现的。
一般而言,异步任务有以下三种类型:
1、普通事件,如click、resize等
2、资源加载,如load、error等
3、定时器,包括setinterval、setTimeout等
异步任务相关添加到任务队列中(任务队列也称为消息队列)。

  • 1.先执行执行栈中的同步任务。
  • 2.异步任务放入任务队列中。
  • 3.一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。

12.4location对象

location的数据类型是对象,它拆分并保存了URL地址的各个组成部分
常用属性和方法:
href属性获取完整的URL地址,对其赋值时用于地址的跳转

//可以得到当前文URL地址
console.log(location.href)
//可以通过js方式跳转到目标地址
location.href = 'http://www.itcast.cn'

search属性获取地址中携带的参数,符号?后面部分

console.log(location.search)

hash属性获取地址中的哈希值,符号#后面部分

后期Vue路由的铺垫,经常用于不刷新页面,显示不同页面,比如网易云音乐

console.log(location.hash)

reload方法用来刷新当前页面,传入参数true时表示强制刷新

<body>
    <button>点击刷新</button>
    <script>
        let btn = document.querySelector('button')
        btn.addEventListener('click', function () {
            location.reload(true)
            // 强制刷新类似ctrL+f5
        })
    </script>
</body>
5秒钟之后跳转的页面

需求:用户点击可以跳转,如果不点击,则5秒之后自动跳转,要求里面有秒数倒计时
分析:
①:目标元素是链接
②:利用定时器设置数字倒计时
③:时间到了,自动跳转到新的页面

<body>
    <a href="http://www.baidu.com">支付将在<span>5</span>s后自动跳转</a>
    <script>
        const a = document.querySelector('a')
        let num = 5
        let timer = setInterval(function () {
            num--
            a.innerHTML = `支付将在${num}s后自动跳转`
            if(num === 0){
                clearInterval(timer)
                location.href="http://www.baidu.com"
            }
        }, 1000)
    </script>
</body>

12.5navigator对象

navigator的数据类型是对象,该对象下记录了浏览器自身的相关信息
常用属性和方法:
通过userAgent检测浏览器的版本及平台


12.6histroy.对象 

history的数据类型是对象,主要管理历史记录,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
常用属性和方法:

history对象方法作用
back()可以后退功能
formard()前进功能
go(参数)前进后退功能 参数如果是1 前进1个页面 如果是-1 后退1个页面
<body>
    <button>前进</button>
    <button>后退</button>
    <script>
        const back = document.querySelector('button:first-child')
        const forward = back.nextElementSibling
        back.addEventListener('click', function () {
            history.go(-1)
        })
        forward.addEventListener('click', function () {
            history.go(1)
        })
    </script>
</body>

13.本地存储


13.1本地存储介绍

以前我们页面写的数据一刷新页面就没有了,是不是?
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。
1、数据存储在用户浏览器中
2、设置、读取方便、甚至页面刷新不丢失数据
3、容量较大,sessionStorage和localStorage约5M左右
常见的使用场景:
https://todomvc.com/examples/vanilla-es6/页面刷新数据不丢失


13.2本地存储分类-localStorage

目标:能够使用localStorage把数据存储的浏览器中
作用:可以将数据永久存储在本地(用户的电脑),除非手动删除,否则关闭页面也会存在
特性:

  • 可以多窗口(页面)共享(同一浏览器可以共享)
  • 以键值对的形式存储使用

存储数据:

localStorage.setltem(key,value)

获取数据:

localStorage.getltem(key)

删除数据:

localStorage.removeltem(key)

    <script>
        //增
        localStorage.setltem('uname', 'pink老师')
        //查
        console.log(localStorage.getltem('uname'))
        //删
        localStorage.removeltem('uname')
        //改 如果原来有这个键,则是改,如果没有这个键,则是增
        localStorage.setltem('uname', 'red老师')

        //我要存一个年龄
        //本地存储只能存储字符串数据类型
        localStorage.setltem('age',18)
        console.log(localStorage.getltem('age')) //打印出来是字符串类型
    </script>

12.3本地存储分类-sessionStorage

特性:

  • 生命周期为关闭浏览器窗口
  • 在同一个窗口(页面)下数据可以共享
  • 以键值对的形式存储使用
  • 用法跟localStorage基本相同

  13.4存储复杂数据类型

目标:能够存储复杂数据类型以及取出数据
本地只能存储字符串,无法存储复杂数据类型.

解决:需要将复杂数据类型转换成SON字符串,在存储到本地
语法:

JSON.stringify(复杂数据类型)
    <script>
       const obj = {
        uname:'pink老师',
        age:18,
        gender:'女'
       }
       localStorage.setItem('obj',JSON.stringify(obj))
       //JSON对象 属性和值有引号,而引号统一是双引号
       //{"uname":"pink老师","age":18,"gender":"女"}
       console.log(localStorage.getItem('obj')) //取出来是字符串
       //把JSON字符串转换为 对象
       console.log(JSON.parse(localStorage.getItem('obj'))) //取出来的是对象
    </script>

14.数组map和join方法

数组中map方法 迭代数组

使用场景:
map可以遍历数组处理数据,并且返回新的数组

    <script>
   const arr = ['red','green','pink']
   //map数组方法
   const newArr = arr.map(function(ele,index){
    console.log(ele)//数组元素
    console.log(index)//索引号
    return ele + '颜色'
   })
   console.log(newArr) //['red颜色', 'green颜色', 'pink颜色']
    </script>

map也称为映射。映射是个术语,指两个元素的集之间元素相互"对应”的关系。
map重点在于有返回值,forEach没有返回值


数组中join方法
作用:
join()方法用于把数组中的所有元素转换一个字符串
语法:

   //2.数组join方法 把数组转换为字符串
   //小括号为空则逗号分割
   console.log(newArr.join()) //red颜色,green颜色,pink颜色
   //小括号是空字符串,则元素之间没有分隔符
   console.log(newArr.join('')) //red颜色green颜色pink颜色
   console.log(newArr.join('|')) //red颜色|green颜色|pink颜色

参数:
数组元素是通过参数里面指定的分隔符进行分隔的,空字符串( ' ' ),则所有元素之间都没有任何字符。


15.正则表达式


15.1介绍

什么是正则表达式:
正则表达式(Regular Expression)是用于匹配字符串中字符组合的模式。在JavaScript中,正则表达式也是对象
通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式。

请在上图中找出【戴帽子和眼镜的男人】
戴帽子、戴眼镜、男人都是描述信息,通过这些信息能够在人群中查找到确定的某个人,那么这些用于查找的描述信息编写一个模式,对应到计算机中就是所谓的正则表达式。


正则表达式在JavaScript中的使用场景:
例如验证表单:用户名表单只能输入英文字母、数字或者下划线,昵称输入框中可以输入中文(匹配)
比如用户名:/^[a-z0-9_-]{3,16}$/
过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等。


15.2语法

我们想要查找是否有戴眼镜的人,怎么做呢?
1.定义规则:戴眼镜的
2.根据规则去查找:找到则返回
正则同样道理,我们分为两步:
1.定义规则
2.查找
比如:查找下面文本中是否包含字符串'前端'

1et str='IT培训,前端开发培训,web前端培训,软件测试培训,产品经理培训'

JavaScript中定义正则表达式的语法有两种,我们先学习其中比较简单的方法:
1.定义正则表达式语法:

//其中/  /是正则表达式字面量
const 变量名=/表达式/

比如

const reg=/前端/

2.判断是否有符合规则的字符串:

//test()方法用来查看正则表达式与指定的字符串是否匹配
regobj.test(被检测的字符串)

比如:

    <script>
        //要检测的字符串
        let str = 'IT培训,前端开发培训,web前端培训,软件测试培训,产品经理培训'
        //1.定义正则表达式,检测规则
        const reg = /前端/
        //检测方法
        console.log(reg.test(str)) //true
    </script>

如果正则表达式与指定的字符串匹配,返回true,否则false

3.检索(查找)符合规则的字符串:

//exec()方法在一个指定字符串中执行一个搜索匹配
regObj.exec(被检测字符串)

比如:

    <script>
        //要检测的字符串
        let str = 'IT培训,前端开发培训,web前端培训,软件测试培训,产品经理培训'
        //1.定义正则表达式,检测规则
        const reg = /前端/
        //检测方法
        console.log(reg.exec(str)) 
        //['前端', index: 5, input: 'IT培训,前端开发培训,web前端培训,软件测试培训,产品经理培训', groups: undefined]
    </script>

如果匹配成功,exec()方法返回一个数组,否则返回null


15.3元字符

目标:能说出什么是元字符以及它的好处
普通字符:
大多数的字符仅能够描述它们本身,这些字符称作普通字符,例如所有的字母和数字。也就是说普通字符只能够匹配字符串中与它们相同的字符。
元字符(特殊字符):
是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能。

  • 比如,规定用户只能输入英文26个英文字母,普通字符的话abcdefghijklm..
  • 但是换成元字符写法:[a-z]

参考文档:
MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions
正则测试工具:http://tool.oschina.net/regex
为了方便记忆和学习,我们对众多的元字符进行了分类:

  • 边界符(表示位置,开头和结尾,必须用什么开头,用什么结尾)

正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符

边界符号说明
^表示匹配行首的文本(以谁开始)
$表示匹配行尾的文本(以谁结束)

如果^和$在一起,表示必须是精确匹配

    // 元字符
    console.log(/哈/.test('哈')) // true
    console.log(/哈/.test('哈哈')) // true
    console.log(/哈/.test('二哈')) // true
    console.log('------------------')
    // 1. 边界符
    console.log(/^哈/.test('哈')) // true
    console.log(/^哈/.test('哈哈')) // true
    console.log(/^哈/.test('二哈')) // flase
    console.log(/^哈$/.test('哈')) // true  只有这种情况为true 否则全是false
    console.log(/^哈$/.test('哈哈')) // false
    console.log(/^哈$/.test('二哈')) // false
  • 量词(表示重复次数)

量词用来设定某个模式出现的次数

量词说明
*重复零次或更多次
+重复一次或更多次
重复零次或一次
{n}重复n次
{n,}重复n次或更多次
{n,m}重复n到m次

    // //  量词 * 类似 >=0 次
    //‘哈’ 能出现0次或无数次,但是不能出现除‘哈’以外的任何字 
    console.log(/^哈$/.test('哈')) // true
    console.log(/^哈*$/.test('')) // true
    console.log(/^哈*$/.test('哈')) // true
    console.log(/^哈*$/.test('哈哈')) // true
    console.log(/^哈*$/.test('二哈很傻')) //  false
    console.log(/^哈*$/.test('哈很傻')) //  false
    console.log(/^哈*$/.test('哈很哈')) // false
    // console.log('------------------')
    // //  量词 + 类似 >=1 次
    console.log(/^哈$/.test('哈')) // true
    console.log(/^哈+$/.test('')) // false
    console.log(/^哈+$/.test('哈')) // true
    console.log(/^哈+$/.test('哈哈')) // true
    console.log(/^哈+$/.test('二哈很傻')) //  false
    console.log(/^哈+$/.test('哈很傻')) //  false
    console.log(/^哈+$/.test('哈很哈')) // false
    // console.log('------------------')
    // //  量词 ? 类似  0 || 1
    console.log(/^哈?$/.test('')) // true
    console.log(/^哈?$/.test('哈')) // true
    console.log(/^哈?$/.test('哈哈')) // false
    console.log(/^哈?$/.test('二哈很傻')) //  false
    console.log(/^哈?$/.test('哈很傻')) //  false
    console.log(/^哈?$/.test('哈很哈')) // false]
    // 量词 {n} 写几,就必须出现几次
    console.log(/^哈{4}$/.test('哈'))// false
    console.log(/^哈{4}$/.test('哈哈'))// false
    console.log(/^哈{4}$/.test('哈哈哈'))// false
    console.log(/^哈{4}$/.test('哈哈哈哈'))// true
    console.log(/^哈{4}$/.test('哈哈哈哈哈'))// false
    console.log(/^哈{4}$/.test('哈哈哈哈哈哈'))// false
    console.log('------------------')
    // 量词 {n,}   >=n
    console.log(/^哈{4,}$/.test('哈'))// false
    console.log(/^哈{4,}$/.test('哈哈'))// false
    console.log(/^哈{4,}$/.test('哈哈哈'))// false
    console.log(/^哈{4,}$/.test('哈哈哈哈'))// true
    console.log(/^哈{4,}$/.test('哈哈哈哈哈'))// true
    console.log(/^哈{4,}$/.test('哈哈哈哈哈哈'))// true
    console.log('------------------')
    // 量词 {n,m}  逗号左右两侧千万不能有空格    >=n && <= m
    console.log(/^哈{4,6}$/.test('哈'))// false
    console.log(/^哈{4,6}$/.test('哈哈'))// false
    console.log(/^哈{4,6}$/.test('哈哈哈'))// false
    console.log(/^哈{4,6}$/.test('哈哈哈哈'))// true
    console.log(/^哈{4,6}$/.test('哈哈哈哈哈'))// true
    console.log(/^哈{4,6}$/.test('哈哈哈哈哈哈'))// true
    console.log(/^哈{4,6}$/.test('哈哈哈哈哈哈哈'))// false
  • 字符类(比如\d表示0~9)

(1) [  ]匹配字符集合
后面的字符串只要包含abc中任意一个字符,都返回true。

    // 字符类   [abc]  只选1个
    console.log(/^[abc]$/.test('a'))  // true
    console.log(/^[abc]$/.test('b'))  // true
    console.log(/^[abc]$/.test('c'))  // true
    console.log(/^[abc]$/.test('ab'))  // false
    console.log(/^[abc]{2}$/.test('ab'))  // true

(2) [  ]里面加上-连字符
使用连字符 - 表示一个范围
[a-z]表示a到z26个英文字母都可以
[a-zA-Z]表示大小写都可以
[0-9]表示0~9的数字都可以

    // 字符类   [a-z]  只选1个
    console.log(/^[A-Z]$/.test('p'))  // false
    console.log(/^[A-Z]$/.test('P'))  // true
    console.log(/^[0-9]$/.test(2))  // true
    console.log(/^[a-zA-Z0-9]$/.test(2))  // true
    console.log(/^[a-zA-Z0-9]$/.test('p'))  // true
    console.log(/^[a-zA-Z0-9]$/.test('P'))  // true

(3) [  ]里面加上^取反符号
比如:
[^a-z]匹配除了小写字母以外的字符
注意要写到中括号里面
(4) . 小数点匹配除换行符之外的任何单个字符

用户名验证案例:


需求:用户名要求用户英文字母,数字,下划线或者短横线组成,并且用户名长度为6~16位
分析:
①:首先准备好这种正则表达式模式/^[a-zA-Z0-9-_]{6,16}$/
②:当表单失去焦点就开始验证
③:如果符合正则规范,则让后面的span标签添加right类
④:如果不符合正则规范,则让后面的span标签添加wrong类.

<!DOCTYPE html>
<html lang="en">

<head>
    <style>
        span {
            display: inline-block;
            width: 250px;
            height: 30px;
            vertical-align: middle;
            line-height: 30px;
            padding-left: 15px;
        }

        .error {
            color: red;
            background: url(./images/error1.png) no-repeat left center;
        }

        .right {
            color: green;
            background: url(./images/right.png) no-repeat left center;
        }
    </style>
</head>

<body>
    <input type="text">
    <span></span>
    <script>
        // 1. 准备正则
        const reg = /^[a-zA-Z0-9-_]{6,16}$/
        const input = document.querySelector('input')
        const span = input.nextElementSibling
        input.addEventListener('blur', function () {
            // console.log(reg.test(this.value))
            if (reg.test(this.value)) {
                span.innerHTML = '输入正确'
                span.className = 'right'
            } else {
                span.innerHTML = '请输入6~16位的英文数字下划线'
                span.className = 'error'
            }
        })
    </script>
</body>

</html>

预定义:指的是某些常见模式的简写方式

预定类说明
\d匹配0-9之间的任一数字,相当于[0-9]
\D匹配所有0-9以外的字符,相当于[^0-9]
\w匹配任意的字母、数字和下划线,相当于[A-Za-z0-9]
\W除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]
\s匹配空格(包括换行符、制表符、空格符等),相等于[\t\r\n\v\f]
\S匹配非空格的字符,相等于[^\t\r\n\v\f]

日期格式:^\d{4}-\d{1,2}-\d{1,2}


15.4修饰符

修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等
语法:

/表达式/修饰符

i是单词ignore的缩写,正则匹配时字母不区分大小写
g是单词global的缩写,匹配所有满足正则表达式的结果

    const str = 'java是一门编程语言, 学完JAVA工资很高'
    const re = str.replace(/java/ig, '前端') // 前端是一门编程语言, 学完前端工资很高
    const re = str.replace(/java/i, '前端') //前端是一门编程语言, 学完JAVA工资很高,只能替换第一个
    const re = str.replace(/java/g, '前端') //前端是一门编程语言, 学完JAVA工资很高,只能替换小写java
    const re = str.replace(/java | Java/g, '前端')// 前端是一门编程语言, 学完前端工资很高
    console.log(re)  
过滤敏感字

需求:要求用户不能输入敏感字
比如,pink老师上课很有**
分析:
①:用户输入内容
②:内容进行正则替换查找,找到敏感词,进行**
③:要全局替换使用修饰符g

<body>
  <textarea name="" id="" cols="30" rows="10"></textarea>
  <button>提交</button>
  <div></div>
  <script>
    const tx = document.querySelector('textarea')
    const button = document.querySelector('button')
    const div = document.querySelector('div')
    button.addEventListener('click', function () {
      const after =tx.value.replace (/激情|激情/g,'**')
      div.innerHTML =  after
      //提交后表单为空
      tx.value = ''
    })
  </script>
</body>


 

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值