JavaScript-核心与进阶

JavaScript-基础

  • Vscode 插件

    • error lens

      效果
    • 快捷键修改

      按下组合键ctrl+k,ctrl+s
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      // Place your key bindings in this file to override the defaultsauto[]
      // ctrl + l: 格式化
      // ctrl + d: 向下复制一行
      // ctrl+shift+u: 转换为大写
      // ctrl+shift+i: 转换为 小写
      [
      {
      "key": "ctrl+l",
      "command": "editor.action.formatDocument",
      "when": "editorHasDocumentFormattingProvider && editorTextFocus && !editorReadonly && !inCompositeEditor"
      },
      {
      "key": "ctrl+d",
      "command": "editor.action.copyLinesDownAction",
      "when": "editorTextFocus && !editorReadonly"
      },
      {
      "key": "ctrl+shift+u",
      "command": "editor.action.transformToUppercase",
      "when": "editorTextFocus"
      },
      {
      "key": "ctrl+shift+i",
      "command": "editor.action.transformToLowercase",
      "when": "editorTextFocus"
      }
      ]
  • 介绍

    • 是什么

      JavaScript 是一种运行在客户端(浏览器)的编程语言,实现人机交互效果

    • 作用

      1. 网页特效(监听用户的一些行为让网页做出对应的反馈)
      2. 表单验证(针对表单数据的合法性进行判断)
      3. 数据交互(获取后台的数据,渲染到前端)
      4. 服务端编程(node.js)
    • 组成

      组成
      • ECMAScript
        • 规定了js 基础语法核心知识
          • 比如:便来给你、分支语句、循环语句、对象等
      • Web Apis
        • DOM: 操作文档,比如对页面元素进行移动、大小、添加删除等操作
        • BOM: 操作浏览器,比如页面弹窗、检测窗口宽度、存储数据到浏览器等等
    • 书写位置

      • 内联

        1
        <button onclick="alert('内联..........');">点击触发</button>
      • 内部

        注意:

        ​ 将script 标签放在HTML文件的底部附近的原因是浏览器会按照代码在文件中的顺序加载 HTML.如果先加载Js 期望修改其下方的HTML,那么他由于HTML 尚未被加载而失效。因此,Js 代码放在HTML 页面的底部附件通常是最好的策略。

        推荐
      • 外部

        1
        2
        3
        4
        5
        6
        7
        8
        9
        <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>Document</title>
        <!-- 外部文件引入 -->
        <script src="./index.js"></script>

        </head>
        1. script 标签中间无需写代码、否则会被忽略
        2. 外部Js 会使代码更加有序,更易于复用、且没有了脚本的混合,HTML 也会更加易读
  • 输入输出

    • 输出

      1
      2
      3
      4
      5
      6
      7
      <script>
      /* *********** 页面输出 *********** */
      document.write("输出语句");
      document.write("

      支持标签解析: 输出语句

      "
      );

      /* *********** 控制台输出 *********** */
      console.log("不支持标签解析: 输出.........");
      </script>
    • 输入

      1
      2
      3
      <script>
      prompt("请输入: ");
      </script>
  • 变量

    • 变量是一个容器

    • 作用: 用来存放数据的。变量是指容器而不是数据

    • 基本使用

      • 声明变量

        1
        let 变量名
      • 变量赋值

        1
        let age = 20;
      • 更新变量

        1
        age = 30;
  • 数组

    • 声明语法

      1
      let arr = [value1,value2,...];
      • 术语
        • 元素: 数组中保存的每个数据都叫做数据元素
        • 下标: 数组中数据的编号
        • 长度: 数组中数据的个数,通过数组的length 属性获得
    • 求最大值

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      <body>
      <script>
      let arr = [20, 1, 0, 100, 67, 50];
      let max = arr[0]
      for (let idx = 1; idx < arr.length; idx++) {
      if (max < arr[idx]) {
      max = arr[idx];
      }
      }
      console.log(max)
      </script>
      </body>

    • 修改

      1
      arr[0] = 10
    • 新增

      1
      2
      arr.push(); // 末尾
      arr.unshift(); // 首个
    • 删除

      1
      2
      3
      arr.pop(); // 删除末尾
      arr.shift(); // 删除首个
      arr.splice(操作的下标,删除的个数);
  • 常量

    • 使用const 声明的变量就是常量
    • 当某个变量永远不会发生改变的时候,就可以使用const 声明
    • 常量不允许重新赋值,声明的时候就必须赋值
  • 数据类型

    • 基本数据类型
      • number 数字型
      • string 字符串型
      • boolean 布尔型
      • undefined 未定义型
      • null 空类型
    • 引用数据类型
      • Object 对象
      • function 函数
      • array 数组
  • 数组遍历

    1
    2
    3
    4
    5
    6
    7
    <script>
    let arr = [1, 2, 3, 4, 5];
    for (let index = 0; index < array.length; index++) {
    console.log(array[index]);
    }
    </script>

  • 对象遍历

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // for in 不适合遍历数组,因为 k 是字符串类型
    <script>
    let info = {
    age: 12,
    name: "张三"
    };

    for (k in info) {
    // String
    console.log(typeof k);
    // 输出元素值
    console.log(info[k]);

    }
    </script>
  • 随机数

    • Math.random() 随机数函数,返回一个0~1 之间,并且包含0 不包含1 的随机小数

    • 生成0 ~ 10 的随机数

      1
      Math.floor(Math.random()) * (10 + 1)
    • 生成5 ~ 10 的随机数

      1
      2
      // bound = 10 - 5 +1   +5
      Math.floor(Math.random() * (5 + 1)) + 5
    • 生成N~M 之间的随机数

      1
      Math.floor(Math.random() * (M - N + 1)) + N

Apis

DOM-获取元素
  • Web API 基本认知

    • 声明变量

      • 建议: const优先使用
      • 原因
        • const 语义化更好
        • 很多变量我们声明的时候就知道他不会被更改了
    • 作用和分类

      • 作用: 就是使用JS 去操作html 和浏览器
      • 分类: DOM(文档对象模型)BOM(浏览器对象模型)
    • 什么是DOM

      • DOM(Document Object Model-文档对象模型) 是用来呈现以及与任意HTML XML 文档交互的API
      • 作用: 开发网页内容特效和实现用户交互
    • DOM

      • HTML 文档以树状结构直观的表现出来,我们称之为文档树或DOM

      • 描述网页内容关系的名词

      • 作用: 文档树直观的体现了标签与标签之间的关系

        DOM
    • DOM 对象: 浏览器根据html 标签生成的JS 对象

      • 所有的标签属性都可以在这个对象上面找到
      • 修改这个对象的属性会自动映射到标签身上
      DOM 对象
      在这里插入图片描述
    • DOM 的核心思想: 把网页内容当做对象来处理

    • document 对象

      • DOM 里提供的一个对象
      • 所以它提供的属性和方法都是用来访问和操作网页内容的
  • 获取DOM 对象

    • 根据CSS 选择器获取

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <body>
      <div class="box">1</div>
      <div class="box">2</div>

      <script>
      // 选择匹配的第一个
      const boxEl = document.querySelector(".box"); // 1
      </script>
      </body>

      1
      2
      3
      4
      5
      6
      7
      8
      9
      <body>
      <div class="box">1</div>
      <div class="box">2</div>
      <script>
      // 获取所有
      const boxEls = document.querySelectorAll(".box");
      console.log(boxEls)
      </script>
      </body>
  • 操作元素内容

    • 文本替换

      • innerHTML

      • innerText

        1
        2
        3
        4
        5
        6
        7
        8
        <body>
        <div class="box">文字内容</div>

        <script>
        const boxEl = document.querySelector(".box");
        boxEl.innerText = 'vba'
        </script>
        </body>
    • 区别

      • innerText 不解析标签

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        <body>
        <div class="box1">文字内容</div>
        <div class="box2">文字内容</div>
        <div class="box3">文字内容</div>

        <script>
        const boxE1 = document.querySelector(".box1");
        const boxE2 = document.querySelector(".box2");
        boxE1.innerHTML = '<strong>InnerHTML</strong>'
        boxE2.innerText = '<strong>InnerText</strong>'
        </script>
        </body>
  • 操作元素属性

    • 操作元素常用属性

      • href、title、src

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        <body>
        <a href="http://www.baidu.com">百度</a><br />
        <img src="./bg.png" alt="" width="100">
        <div title="div">div content</div>
        <script>
        /* ****************** 属性值修改 *************** */
        const aE1 = document.querySelector("a");
        const aE2 = document.querySelector("img");
        const aE3 = document.querySelector("div");

        aE1.href = "http://jd.com"
        aE2.src="bg2.png"
        /* ******************************************** */
        </script>
        </body>
    • 操作元素样式属性

      • 通过style 属性操作css

        1
        aE2.style.border = "1px solid blue";
      • 操作类名操作css

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        <style>
        img{
        border: 1px solid red;
        padding: 10px;
        }
        .jsAdd{
        border: 2px solid green;
        }
        </style>

        <script>
        const aE2 = document.querySelector("img");
        aE2.className = 'jsAdd'
        </script>
      • 通过classList 操作类控制css

        • 追加一个类

          1
          2
          const aE1 = document.querySelector("a");
          aE1.classList.add("jsAdd1");
        • 删除一个类

          1
          aE1.classList.remove("jsAdd2");
        • 切换一个类

          1
          aE1.classList.toggle("jsAdd2");     
    • 操作表单元素属性

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      <!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>Document</title>
      <style>
      span {
      display: block;
      cursor: pointer;
      }
      </style>
      </head>

      <body>
      <form action="">
      <input type="text" name="username" id="username">
      <input type="password" name="password" id="password">
      <span>v</span>
      </form>
      <script>
      // 获取元素
      const username = document.querySelector("#username");
      const password = document.querySelector("#password");
      const span = document.querySelector("span");

      span.onclick = function () {
      console.log(username.value)
      password.type = password.type == "password" ? "text" : "password"
      }

      </script>
      </body>

      </html>
    • 自定义属性

      • html5 中推出来了专门的data-自定义属性

      • 在标签上一律以data-开头

      • DOM 对象上一律以dataset 对象方式获取

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        <body>
        <div data-id="1"></div>
        <div data-name="lisi"></div>

        <script>
        const divEl = document.querySelector("div");
        console.log(divEl.dataset.id)
        </script>
        </body>

  • 定时器-间歇函数

    • setInterval

      1
      2
      3
      4
      5
      6
      7
      <script>
      // setInterval(函数, 间歇时间(ms))
      let timer = setInterval(() => {
      console.log("1.......")
      }, 1000);
      clearInterval(timer)
      </script>
  • 综合案例

DOM-事件基础
  • 事件监听

    • 什么是事件

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

    • 什么是事件监听

      就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也成为绑定事件或注册事件

    • 语法

      1
      元素对象.addEventListener('事件类型',要执行的函数)
      • 事件监听三要素
        • 事件源: 那个dom 元素被事件触发了,要获取dom 元素
        • 事件类型: 用什么方式触发,比如鼠标单机click、鼠标经过mouseover
        • 事件调用的函数: 要做什么事
  • 事件类型

    • 鼠标事件
      • click 鼠标点击
      • mouseenter 鼠标经过
      • mouseleave 鼠标离开
    • 焦点事件
      • focus: 获取焦点
      • blur: 失去焦点
    • 键盘触发
      • keydown: 键盘按下触发
      • keyup: 键盘抬起触发
    • 表单输入触发
      • input 用户输入事件
  • 事件对象

    • 是什么

      • 也是个对象,这个对象里面有事件触发时的相关信息
      • 例如: 鼠标点击事件中,事件对象就存了鼠标点在那个位置等信息
    • 获取事件对象

      • 在事件绑定的回调函数的第一个参数就是事件对象
      • 一般命名为event、ev、e
    • 事件对象常用属性

      • type: 获取当前的事件类型

      • clientX/clientY: 获取光标相对于浏览器可见窗口左上角的位置

      • offsetX/offsetY: 获取光标相对于当前DOM 元素最上交的位置

      • key

        • 用户按下的键盘键的值

        • 现在不提倡使用keyCode

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          <body>
          <input type="text" name="" id="">
          <script>
          const input = document.querySelector("input");
          input.addEventListener("keyup", (e) => {
          if (e.key === 'Enter') {
          console.log(e)
          }
          })
          </script>
          </body>
  • 环境对象

    • 指的是函数内部特殊的变量 this,它代表当前函数运行时所处的环境
    • 作用
      • 函数的调用方式不同,this 指代的对象也不同
      • 谁调用,this就是谁是判断this 指向的粗略规则
      • 直接调用函数,其实相当于使用window.函数,所以this 指向window
  • 回调函数

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

  • 综合案例

    • Tab-栏切换
    • 全选、反选
DOM-事件进阶
  • 事件流

    • 事件流与两个阶段说明

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

        事件流与两个阶段
  • 事件冒泡

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

    1
    2
    // 此方法可以阻断事件流动传播 不光在冒泡阶段有效,在捕获阶段也同样有效
    e.stopPropagation();
  • 解绑事件

    • on

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      <body>
      <button>点击</button>
      <script>
      const btlEl = document.querySelector("button");
      btlEl.onclick = function () {
      alert(1);
      // 事件解绑
      btlEl.onclick = null;
      }
      </script>
      </body>
    • addEventListener

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      // 匿名函数无法解绑
      <body>
      <button>点击</button>
      <script>
      const btlEl = document.querySelector("button");
      function test() {
      alert(2)
      btlEl.removeEventListener('click', test)
      }
      btlEl.addEventListener('click', test)
      </script>
      </body>

  • 鼠标经过事件

    • mouseover mouseout 会有冒泡效果
    • mouseenter mouseleave 没有冒泡效果【推荐
  • 事件委托

    • 事件委托是利用事件流的特征解决一些开发需求的只是技巧

      • 有点: 减少注册次数,可以提高程序性能

      • 原理: 事件委托其实是利用事件冒泡的特点

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

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

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        <!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>Document</title>
        <style>
        li {
        float: left;
        width: 25px;
        height: 25px;
        margin: 5px;
        font-size: 12px;
        background-color: skyblue;
        line-height: 25px;
        text-align: center;
        list-style: none;
        }

        ul {
        overflow: hidden;
        }
        </style>
        </head>

        <body>
        <ul>
        <li data-id="1">1</li>
        <li data-id="2">2</li>
        <li data-id="3">3</li>
        <li data-id="4">4</li>
        <li data-id="5">5</li>
        <p>我不需要变色</p>
        </ul>

        <script>
        const ulEl = document.querySelector("ul");
        const _this = this;
        ulEl.addEventListener('click', (e) => {
        // e.target 点击对象
        console.dir(e.target)
        if (e.target.tagName === "LI") {
        e.target.style.backgroundColor = "red"
        }
        });
        </script>
        </body>

        </html>
        dir => tagName
    • 点击那个那个背景颜色发生变化

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      <!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>Document</title>
      <style>
      li {
      float: left;
      width: 25px;
      height: 25px;
      margin: 5px;
      font-size: 12px;
      background-color: skyblue;
      line-height: 25px;
      text-align: center;
      list-style: none;
      }

      ul {
      overflow: hidden;
      }

      .active {
      background-color: red;
      }
      </style>
      </head>

      <body>
      <ul>
      <li data-id="1" class="active">1</li>
      <li data-id="2">2</li>
      <li data-id="3">3</li>
      <li data-id="4">4</li>
      <li data-id="5">5</li>
      <p>我不需要变色</p>
      </ul>

      <script>
      const ulEl = document.querySelector("ul");

      ulEl.addEventListener('click', (e) => {
      // e.target 点击对象
      console.dir(e.target)
      if (e.target.tagName === "LI") {
      // 排除其他的
      document.querySelector("ul .active").classList.remove("active")
      e.target.classList.add("active")
      }
      });
      </script>
      </body>

      </html>
    • Tab 栏切换

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      <!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>Document</title>
      <style>
      li {
      float: left;
      width: 25px;
      height: 25px;
      margin: 5px;
      font-size: 12px;
      background-color: skyblue;
      line-height: 25px;
      text-align: center;
      list-style: none;
      }

      ul {
      overflow: hidden;
      }

      .tab ul .active {
      display: block;
      background-color: rgb(204, 146, 146);
      }

      .tab ul {
      /* width: 310px; */
      height: 310px;
      /* overflow: hidden; */
      }

      .tab ul li {
      display: none;
      width: 300px;
      height: 300px;
      border: 1px solid #000;
      }
      </style>
      </head>

      <body>
      <ul>
      <li data-id="1" class="active">1</li>
      <li data-id="2">2</li>
      <li data-id="3">3</li>
      <li data-id="4">4</li>
      <li data-id="5">5</li>
      </ul>
      <div class="tab">
      <ul>
      <li class="item active" data-id="1">1</li>
      <li class="item" data-id="2">2</li>
      <li class="item" data-id="3">3</li>
      <li class="item" data-id="4">4</li>
      <li class="item" data-id="5">5</li>
      </ul>
      </div>

      <script>
      const ulEl = document.querySelector("ul");
      // 实现 2 allTabs => []
      const allTabs = document.querySelectorAll(".tab .item")
      console.log(allTabs)
      ulEl.addEventListener('click', (e) => {
      // e.target 点击对象
      console.dir(e.target)
      // id => number
      const id = +e.target.dataset.id;
      if (e.target.tagName === "LI") {
      // 排除其他的
      document.querySelector("ul .active").classList.remove("active")
      document.querySelector(".tab .active").classList.remove("active")

      e.target.classList.add("active")
      // 实现 1
      // document.querySelector(`.tab .item:nth-child(${id})`).classList.add("active")
      // id - 1 是因为数组下标从 0 开始
      allTabs[id - 1].classList.add("active")
      }
      });
      </script>
      </body>

      </html>
      Tab 栏切换
  • 阻止默认行为

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <body>
    <a href="http://www.baidu.com">Baidu</a>
    <form action="http://www.baidu.com">
    <input type="submit" value="提交">
    </form>
    <script>
    const form = document.querySelector("form");
    const a = document.querySelector("a");
    /************************ form submit **************************/
    form.addEventListener("submit", (e) => {
    e.preventDefault();
    })

    /************************ a click *******************************/
    a.addEventListener("click", (e) => {
    e.preventDefault();
    })
    </script>
    </body>

  • 其他事件

    • 页面加载事件

      加载外部资源(入图片、外联CSS、JavaScript 等)加载完毕时触发的事件

      • 事件名:load

        • 作用: 监听页面所有资源加载完毕

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          <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>Document</title>
          <script>
          window.addEventListener("load", () => {
          const btnEl = document.querySelector("button");
          btnEl.addEventListener("click", () => {
          alert("btn click............")
          })
          })
          </script>
          </head>

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

          </html>
      • 事件名:DOMContentLoaded

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

          1
          2
          3
          4
          5
          <script>
          document.addEventListener("DOMContentLoaded",()=>{

          })
          </script>
    • 元素滚动事件

      • 事件名:scroll

        • scrollLeft、scrollTop:获取被去的大小

          scrollTop
        • 获取元素内容往左、往上滚出去看不到的距离

        • 这两个值可以读写

    • html 元素的获取方式

      1
      const html = document.documentElement;
      html
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      <style>
      html {
      height: 3000px;
      }
      </style>


      <script>
      window.addEventListener("scroll", () => {
      console.log(document.documentElement.scrollTop);
      })
      </script>
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      <!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>Document</title>
      <style>
      * {
      margin: 0;
      padding: 0;
      }

      .header {
      width: 100%;
      height: 80px;
      line-height: 80px;
      text-align: center;
      background-color: cornflowerblue;
      transition: all ease-in-out .2s;
      }

      .box {
      position: absolute;
      left: 0;
      right: 0;

      top: 80px;
      width: 960px;
      height: 1500px;
      background-color: #e5e5e5;
      border: 2px solid red;
      margin: auto;
      }

      .flag {
      margin-top: 300px;
      width: 100px;
      height: 100px;
      background-color: red;
      }

      .header-pro {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      z-index: 1;
      }
      </style>
      </head>

      <body>
      <div class="header">
      顶部导航
      </div>
      <div class="box">
      <div class="flag"></div>
      </div>

      <script>
      const header = document.querySelector(".header");
      const flag = document.querySelector(".flag");
      window.addEventListener("scroll", () => {
      if (document.documentElement.scrollTop >= flag.offsetTop) {
      header.classList.add("header-pro")
      }
      })
      </script>
      </body>

      </html>
    • 页面尺寸事件

      • 事件名: resize

        • 作用: 会在窗口改变的时候触发事件

          1
          2
          3
          4
          5
          <script>
          window.addEventListener("resize", () => {
          console.log(1);
          })
          </script>
      • 获取宽高

        • 获取元素的可见部分宽高(不包含边框、margin、滚动条等)
        • clentWidth && clientHeight
    • 元素的尺寸与位置

      • 获取宽高

        • 获取元素的自身宽高、包含元素自身设置的宽高、padding、border
        • offsetWidth && offsetHeight
        • 获取出来的是数值,方便计算
      • 获取位置

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

        • offsetLeft 、offsetTop 是只读属性

          1
          2
          3
          4
          5
          6
          7
          <script>
          const div = document.querySelector("div")
          const offLeft = div.offsetLeft;
          const offTop = div.offsetHeight;
          console.log(offLeft);
          console.log(offTop);
          </script>
          offsetLeft
        • 滑块

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41
          42
          43
          44
          45
          46
          47
          48
          49
          50
          51
          52
          53
          54
          55
          56
          57
          58
          59
          60
          61
          62
          63
          64
          <!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>Document</title>
          <style>
          * {
          margin: 0;
          padding: 0;
          box-sizing: border-box;
          }

          .box {
          position: relative;
          display: flex;
          text-align: center;
          width: 400px;
          }

          .box a {
          flex: 1;
          padding: 5px 10px;
          margin: 3px;
          }

          .box .line {
          position: absolute;
          left: 3px;
          top: 32px;
          width: 61px;
          height: 2px;
          background-color: red;
          transition: all .3s;
          }
          </style>
          </head>

          <body>
          <div class="box">
          <a href="javascript:void(0);">首页</a>
          <a href="javascript:void(0);">首页</a>
          <a href="javascript:void(0);">首页</a>
          <a href="javascript:void(0);">首页</a>
          <a href="javascript:void(0);">首页</a>
          <a href="javascript:void(0);">首页</a>
          <div class="line"></div>
          </div>
          <script>
          const box = document.querySelector(".box");
          const line = document.querySelector(".box .line");
          box.addEventListener("click", (e) => {
          if (e.target.tagName === "A") {
          // 获取点击对象
          console.log(e.target.offsetLeft)
          line.style.left = `${e.target.offsetLeft}` + "px";
          }
          })
          </script>
          </body>

          </html>
          下划线移动
  • 总结

    属性 作用 说明
    scrollscrollTop 被卷去的头部和左侧 配合页面滚动来用, 可读写
    clientWidthclientHeight 获得元素宽度和高度 不包含border、margin 滚动条用于js 获取元素大小,只读属性
    offsetwidthoffsetHeight 获得元素宽度和高度 包含 border、padding、滚动条等、只读
    offsetLeftoffsetTop 获取元素距离自己定位父级元素的左、上距离 获取元素位置的时候使用,只读属性
DOM-节点操作
  • 节点操作

    • DOM 节点: DOM 树里面每一个内容都称之为节点

    • 节点类型

      • 元素节点
        • 所有的标签比如body、div
        • html 是根节点
      • 属性节点
        • 所有的属性比如href
      • 文本节点
        • 所有的文本
    • 创建节点

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      <body>
      <ul>
      <li>first</li>
      </ul>
      <script>
      let ul = document.querySelector("ul")
      let li = document.createElement("li")
      // ul.appendChild(li) 末尾
      ul.insertBefore(li, ul.children[0]) // 指定位置
      </script>
      </body>
    • 节点克隆和删除

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

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

        • 若为false,则达标克隆时不包含后代节点

        • 默认为false

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          <body>
          <ul>
          <li>1</li>
          <li>2</li>
          <li>3</li>
          </ul>
          <script>
          const ul = document.querySelector("ul")
          let cll = ul.children[0].cloneNode(true)
          ul.appendChild(cll)
          </script>
          </body>
        • 删除节点

          • 语法

            1
            父元素.removeChild(要删除的元素);
          • 注意

            • 如不存在父子关系则删除不成功
            • 删除节点和隐藏节点(display:none)有区别
数组高阶函数
  • map: 遍历、数据处理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <body>
    <script>
    let arr = [1, 2, 3, 4]
    let newArr = arr.map((item, index) => {
    // 数据处理
    return item + 10
    })
    console.log(newArr);
    </script>
    </body>
  • join

日期对象

  • 日期对象: 用来表示事件的对象

  • 作用: 可以得到当前系统的时间

  • 创建一个时间对象并获取时间

    1
    2
    3
    4
    5
    <script>
    const date = new Date();
    // Fri Feb 24 2023 20:06:53 GMT+0800 (中国标准时间)
    console.log(date)
    </script>
  • 获取时间戳

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <body>
    <script>
    let date1 = new Date()
    // 1. getTime()
    console.log(date1.getTime())
    // 2. +
    let date2 = +new Date()
    console.log(date2)
    </script>
    </body>
  • 倒计时实现

    • 分析

      • 用将来时间减去现在时间就是剩余的时间
      • 核心: 使用将来的时间戳减去现在的时间戳
      • 把剩余的时间转换为天时分秒
    • 注意

      • 通过时间戳得到的是毫秒,需要转换为秒在计算

      • 转换公式

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        <body>
        <script>
        let d = parseInt(总秒数 / 60 / 60 / 24) // 计算天数
        let h = parseInt(总秒数 / 60 / 60 % 24) // 计算小时
        let m = parseInt(总秒数 / 60 % 60) // 计算分数
        let s = parseInt(总秒数 % 60) // 计算当前秒数
        </script>
        </body>


        <body>
        <script>
        // 获取当前的毫秒数
        let now = +new Date();
        // 获取将来时间的毫秒数
        let last = +new Date("2023-2-27 16:00:00");
        // 剩余秒数
        let count = (last - now) / 1000;
        let d = parseInt(count / 60 / 60 / 24) // 计算天数

        let h = parseInt(count / 60 / 60 % 24) // 计算小时
        h = h < 10 ? '0' + h : h;

        let m = parseInt(count / 60 % 60) // 计算分数
        m = m < 10 ? '0' + m : m;

        let s = parseInt(count % 60) // 计算当前秒数
        s = s < 10 ? '0' + s : s;

        console.log(d, h, m, s)
        </script>
        </body>

Window 对象

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

    BOM
  • 延迟函数

    1
    2
    3
    4
    5
    <script>
    setTimeout(() => {
    console.log(1)
    }, 2000)
    </script>
  • JS 执行机制

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

    这是因为JavaScript 这门脚本语言诞生的使命所致-Javascript 是为处理页面中用户的交互,以及操作DOM 而产生的。比如我们对某个DOM 元素进行添加和删除操作,不能同时进行。应该先进行添加,之后在删除。

    单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

    为了解决这个问题,利用多核CPU 的计算能力,HTML5 提出Web Worker 标准,允许JavaScript 脚本创建多个线程,于是JS 中出现了同步和异步

    • 同步: 前一个任务结束后再执行后一个任务

    • 异步: 在处理这件事时可以去处理其他事

    • 事件循环

      事件循环流程
      在这里插入图片描述

      由于主线程不断地重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环(event loop)

  • location 对象

    • location 的数据类型是对象,他拆分并保存了URL 地址的各个组成部分

    • href 实现自动跳转

      1
      location.href="http://www.baidu.com"
      • 案例实现

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        // 需求: 用户点击可以跳转,如果不点击,则 5s 后自动跳转,要求里面有秒数倒计时
        <!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>Document</title>
        <style>
        span {
        color: rgb(236, 171, 87);
        }
        </style>
        </head>
        <body>
        <a href="http://www.baidu.com">前往百度,剩余 <span>5</span></a>
        <script>
        const aEl = document.querySelector("a");
        let time = 15;
        let timer = setInterval(() => {
        time--;
        aEl.innerHTML = `前往百度,剩余 ${time}</span> 秒钟后跳转到百度`;
        if (time === 0) {
        location.href = "http://www.baidu.com";
        clearInterval(timer);
        }
        }, 1000);

        aEl.addEventListener("click", () => {
        location.href = "http://www.baidu.com";
        });
        </script>
        </body>
        </html>

    • location.search 获取表单等 ? 后面的部分

      获取参数
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      <body>
      <form action="">
      <input type="text" name="uname" id="" />
      <button>提交</button>
      </form>

      <script>
      // ?uname=coder-itl
      console.log(location.search);
      </script>
      </body>
    • location.hash

    • location.reload 刷新

    • navigatorhistory 对象

      • navigator 的数据类型是对象,该对象记录了浏览器自身的相关信息

      • navigator 常用属性和方法

        • 通过userAgent 检测浏览器的版本以及平台

          1
          console.log(navigator);
      • history 的数据类型是对象,主要管理历史记录,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等

        • go() 前进后退,参数如果是1,前进一个页面,如果是-1 后退一个页面
        • forward 前进
        • back 后退
  • 本地存储localStorage

实战项目

  • 小兔仙儿

    1
    https://megasu.gitee.io/erabbit-client-pc-document/guide/01-intro.html#_01-%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D
  • 放大镜效果实现

    • 业务分析
      1. 鼠标经过对应小盒子,左侧中等盒子显示对应中等图片
      2. 鼠标经过小盒子,右侧会显示放大镜效果的大盒子
      3. 黑色遮罩盒子跟着鼠标来移动
      4. 鼠标在小盒子上移动,大盒子的图片跟着显示对应位置