作用和分类

作用: 就是使用 JS 去操作 html 和浏览器

分类:DOM (文档对象模型)、BOM(浏览器对象模型)

Web API - 图2

什么是DOM

lDOM(Document Object Model——文档对象模型)是用来呈现以及与任意 HTML 或 XML文档交互的API

白话文:DOM是浏览器提供的一套专门用来 操作网页内容 的功能

lDOM作用

开发网页内容特效和实现用户交互。

DOM树

  1. 将 HTML 文档以树状结构直观的表现出来,我们称之为文档树或 DOM 树
  2. 描述网页内容关系的名词
  3. 作用:文档树直观的体现了标签与标签之间的关系
  4. Web API - 图3

节点

说明

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

nodeType常用属性值

nodeType值 节点类型
1 元素节点,例如
3 文本节点
8 注释节点
9 document节点
10 DTD节点

节点的关系

关系 考虑所有节点(包括文本节点) 只考虑元素节点
子节点 childNodes children
父节点 parentNode parentNode
第一个子节点 firstChild firstElementChild
最后一个节点 lastChild lastElementChild
前一个子节点 previousSibling previousElementSibling
后一个子节点 nextSibling nextElementSibling

节点类型

元素节点

  1. 所有的标签 比如 body、 div
  2. html 是根节点

属性节点

  1. 所有的属性 比如 href

文本节点

  1. 所有的文本

父节点查找

  1. parentNode属性
  2. 返回最近一级的父节点 找不到返回为null
  1. 子元素.parentNode
  • 案例
  1. <div>
  2. <p>去领红包</p>
  3. <img src="./imgs/gd.png" alt="">
  4. <span><img src="./imgs/1.png" alt=""></span>
  5. </div>
  6. <script>
  7. let span = document.querySelector("span");
  8. //点击span让他的父节点也就是div整个隐藏
  9. span.addEventListener('click', function() {
  10. span.parentNode.style.display = 'none'
  11. })

子节点查找

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

children (重点)
  1. 仅获得所有元素节点
  2. 返回的还是一个伪数组
  1. 父元素.children
  1. //需求:点击哪个ul,哪个ul的所有li都隐藏
  2. <ul>
  3. <li>1</li>
  4. <li>2</li>
  5. <li>3</li>
  6. <li>4</li>
  7. </ul>
  8. <ul>
  9. <li>1</li>
  10. <li>2</li>
  11. <li>3</li>
  12. <li>4</li>
  13. </ul>
  14. <ul>
  15. <li>1</li>
  16. <li>2</li>
  17. <li>3</li>
  18. <li>4</li>
  19. </ul>
  20. <script>
  21. let uls = document.querySelectorAll("ul");
  22. for (let i = 0; i < uls.length; i++) {
  23. uls[i].addEventListener('click', function() {
  24. for (let j = 0; j < this.children.length; j++) {
  25. // 得到的子元素是伪数组,所以需要遍历才能得到每个元素
  26. this.children[j].style.display = 'none'
  27. }
  28. })
  29. }
  30. </script>

兄弟节点查找

下一个兄弟节点
  • nextElementSibling属性

上一个兄弟节点
  • previousElementSibling 属性

案例

  1. <ul>
  2. <li>1</li>
  3. <li>2</li>
  4. <li>3</li>
  5. <li>4</li>
  6. <li>5</li>
  7. </ul>
  8. <script>
  9. let lis = document.querySelectorAll("li");
  10. // 循环遍历li标签
  11. for (let i = 0; i < lis.length; i++) {
  12. lis[i].addEventListener('click', function() {
  13. // 上一个兄弟节点变粉
  14. this.previousElementSibling.style.backgroundColor='pink';
  15. // 下一个兄弟节点变蓝
  16. this.nextElementSibling.style.backgroundColor = 'skyblue';
  17. })
  18. }
  19. </script>

增加节点

  • 即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点
  1. <ul>
  2. <li></li>
  3. </ul>
  4. <script>
  5. let ul = document.querySelector("ul")
  6. // 必须要声明获取li才能给他添加样式什么的
  7. let li = document.createElement("li");
  8. //给ul增加节点
  9. ul.appendChild(li)
  10. li.style.backgroundColor = 'pink'
  11. li.innerText = '被插入的li'
  12. </script>

先创建节点
  • 即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点
  • 创建元素节点方法:
    1. document.createElement('标签名')

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

    1. 父元素.appendChild(要插入的元素)


    Web API - 图4

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

    1. 父元素.insertBefore(要插入的元素,在哪个元素前面)
  1. <ul class="right">
  2. <li>1</li>
  3. <li>2</li>
  4. <li>3</li>
  5. <li>4</li>
  6. </ul>
  7. <script>
  8. // insertBefore 也能插入元素 功能也类似 appendChild。
  9. // 1 如果要插入的元素 是已经存在的,那么insertBefore作用 移动
  10. // 2 如果要插入的元素 是新创建的 insertBefore作用 仅仅 插入
  11. let leftLi = document.querySelector('.left li:nth-child(3)');
  12. let two = document.querySelector('.right li:nth-child(2)');
  13. let right = document.querySelector('.right');
  14. // 在右边添加父元素就是右边的ul,在右边的第二个li也就是two前面添加
  15. right.insertBefore(leftLi, two);
  16. let li = document.createElement('li');
  17. li.innerText = '新创建的';
  18. right.insertBefore(li, two);
  19. // 父元素.insertBefore(要插入的元素,哪个元素的上面);
  20. </script>

克隆节点

复制一个原有的节点

  • 把复制的节点放入到指定的元素内部
  • cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值
  1. 元素.cloneNode(布尔值)
  • 若为true,则代表克隆时会包含后代节点一起克隆—深拷贝。
  • 若为false,则代表克隆时不包含后代节点—浅拷贝。(默认false)

删除节点

  • 若一个节点在页面中已不需要时,可以删除它
  • 在 JavaScript 原生DOM操作中,要删除元素节点,元素节点不能主动删除自己,必须由父节点删除 必须通过父元素删除
  • 语法
    1. 父元素.removeChild(要删除的元素)
  • 如不存在父子关系则删除不成功
  • 删除节点和隐藏节点(display:none 有区别的:
    隐藏节点还是存在的,但是删除则从html中删除节点

DOM对象

  1. 浏览器根据html标签生成的 JS对象
  2. 所有的标签属性都可以在这个对象上面找到
  3. 修改这个对象的属性会自动映射到标签身上

lDOM的核心思想

把网页内容当做对象来处理

document 对象

  1. 是 DOM 里提供的一个对象
  2. 所以它提供的属性和方法都是用来访问和操作网页内容的
  3. 例:document.write()
  4. 网页所有内容都在document里面

获取dom元素

查找元素DOM元素就是选择页面中标签元素

根据CSS选择器来获取

选择匹配的第一个元素

  1. 语法:
  2. document.querySelector('css选择器')
  3. 参数:
  4. 包含一个或多个有效的CSS选择器 字符串

返回值:

  1. CSS选择器匹配的第一个元素,一个 HTMLElement对象。
  2. 如果没有匹配到,则返回null。
  3. querySelector() 方法获取到的元素能直接操作修改

选择匹配的多个元素

  1. 语法:
  2. document.querySelectAll('css选择器')
  3. 参数:
  4. 包含一个或多个有效的CSS选择器 字符串

返回值:

CSS选择器匹配的NodeList 对象集合

  1. 得到的是一个伪数组

    1. 有长度有索引号的数组,但是没有 pop() push() 等数组方法。
  2. 哪怕只有一个元素,通过querySelectAll() 获取过来的也是一个伪数组,里面只有一个元素而已。

  3. 想要得到里面的每一个对象,则需要遍历(如 for)的方式获得。

其他获取方式

了解

  1. document.getElementById('id名');
  2. document.getElementByTagName('div');
  3. document.getElementByClassName('选择器名')

设置/修改DOM元素内容

  1. DOM对象都是根据标签生成的,所以操作标签,本质上就是操作DOM对象。
  2. 就是操作对象使用的点语法。

document.write() 方法

  1. 只能将文本内容追加到 前面的位置
  2. 文本中包含的标签会被解析

对象.innerText 属性

  1. 将文本内容添加/更新到任意标签位置
  2. 文本中包含的标签不会被解析
  3. 只能以纯文本的形式设置节点中的内容

对象.innerHTML 属性

  1. 将文本内容添加/更新到任意标签位置
  2. 文本中包含的标签会被解析

设置/修改元素常用属性

最常见的属性比如: href、title、src 等。

  1. 语法:
  2. 对象.属性 =
  3. let pic = document.querySelector('img');
  4. pic.src = './images/1.png';
  5. pic.title = '标题';

通过 style 属性操作CSS

  1. 对象.style.样式属性 =
  1. 修改样式通过style属性引出
  2. 如果属性有-连接符,需要转换为小驼峰命名法
  3. 赋值的时候,需要的时候不要忘记加css单位

操作类名(className) 操作CSS

  1. 元素.className = '类名'
  1. 修改的样式多,直接通过style属性修改比较繁琐,我们可以通过借助于css类名的形式。
  2. className是使用新值换旧值, 如果需要添加一个类,需要保留之前的类名。

通过 classList 操作类控制CSS

  1. //追加一个类
  2. 元素.classList.add('类名')
  3. //删除一个类
  4. 元素.classList.remove('类名')
  5. //切换一个类
  6. 元素.classList.toggle('类名')

为了解决className 容易覆盖以前的类名,我们可以通过classList方式追加和删除类名

设置/修改 表单元素属性

  1. 获取: DOM对象.属性名
  2. 设置: DOM对象.属性名 = 新值
  3. 表单.value = '用户名'
  4. 表单.type = 'password'
  5. //单选框
  6. radio.checked = true //选中
  7. //复选框
  8. checkbox.checked = false //取消选中
  • 表单很多情况,也需要修改属性,比如点击眼睛,可以看到密码,本质是把表单类型转换为文本框。
  • 正常的有属性有取值的 跟其他的标签属性没有任何区别。
  • 表单属性中添加就有效果,移除就没有效果,一律使用布尔值表示 如果为true 代表添加了该属性 如果是false 代表移除了该属性
    比如:disabled、checked、selected
  • innerText innerHTML 主要是用来设置 双标签的文本内容的
    input
    ```javascript 要被更改的文字

let userName = document.querySelector(“.userName”); // innerText innerHTML 主要是用来设置 双标签的文本内容的 userName.innerText = ‘不会有变化呀’ serName.value = ‘有变化了呀’

  1. <a name="Button"></a>
  2. ##### Button
  3. <a name="Select"></a>
  4. ##### Select
  5. <a name="cb375de3"></a>
  6. ##### 文本域textarea
  7. <a name="10b2761d"></a>
  8. ## 事件
  9. <a name="3356c263"></a>
  10. ### 什么是事件
  11. 1. 事件是在编程时系统内发生的**动作**或者发生的事情
  12. 1. 比如用户在网页上**单击**一个按钮
  13. <a name="ba62f7ef"></a>
  14. ### **事件监听**
  15. 1. 让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 注册事件
  16. ```javascript
  17. 元素.addEvenListerener('事件',要执行的函数)

事件取消绑定

  1. removeEventListener 可以取消对应的事件类型和事件处理函数
  2. 无法取消addEventListener 事件对应的匿名函数
  3. 元素.addEventListener(‘事件’,处理函数名称)
  1. <button>按钮</button>
  2. <script>
  3. let btn = document.querySelector("button");
  4. // 匿名函数 无法取消绑定
  5. btn.addEventListener('click', function() {
  6. console.log('hh');
  7. })
  8. function fun1() {
  9. console.log('fun1');
  10. }
  11. // 绑定事件
  12. btn.addEventListener('click', fun1);
  13. // 取消绑定
  14. btn.removeEventListener('click', fun1)
  15. </script>

事件监听三要素:

  1. 事件源: 那个dom元素被事件触发了,要获取dom元素
  2. 事件: 用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等
  3. 事件调用的函数: 要做什么事

事件类型

鼠标事件

鼠标触发

  1. click 鼠标点击
  2. mouseenter 鼠标经过
  3. mouseleave 鼠标离开

焦点事件

表单获得光标

  1. focus 获得焦点
  2. blur 失去焦点

键盘事件

  1. Keydown 键盘按下触发
  2. Keyup 键盘抬起触发

文本事件

  1. 表单输入触发
  2. input 用户输入事件

事件对象

描述

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

获取

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

部分常用属性

type

  • 获取当前的事件类型

获取鼠标位置

属性
clientX 获取光标相对于浏览器
的水平位置
clientY 获取光标相对于浏览器
的垂直位置
offsetX 获取光标相对于整张网页
的水平位置
offsetY 获取光标相对于整张网页
的垂直位置
pageX 获取光标相对于当前DOM元素
的水平位置
pageY 获取光标相对于当前DOM元素
的垂直位置

案例

// 图片跟着鼠标移动
Web API - 图5

  1. ```javascript
  2. //练习-右键菜单
  3. <style>
  4. * {
  5. margin: 0;
  6. padding: 0;
  7. box-sizing: border-box;
  8. }
  9. body {
  10. height: 100vh;
  11. }
  12. .menu {
  13. /* 固定定位 */
  14. position: fixed;
  15. width: 150px;
  16. height: 200px;
  17. background-color: rgb(255, 255, 255);
  18. text-align: center;
  19. display: none;
  20. }
  21. li {
  22. list-style: none;
  23. border: 1px solid #ccc;
  24. padding: 10px;
  25. }
  26. li:hover {
  27. background-color: skyblue;
  28. }
  29. </style>
  30. </head>
  31. <body>
  32. <ul class="menu">
  33. <li>选择1</li>
  34. <li>选择2</li>
  35. <li>选择3</li>
  36. <li>选择4</li>
  37. </ul>
  38. <script>
  39. const menu = document.querySelector(".menu");
  40. document.body.addEventListener('contextmenu', function(event) {
  41. event.preventDefault();
  42. const left = event.clientX;
  43. const top = event.clientY;
  44. menu.style.display = "block"
  45. menu.style.left = left + 'px'
  46. menu.style.top = top + 'px'
  47. });
  48. document.body.addEventListener("click", function() {
  49. menu.style.display = 'none'
  50. })
  51. </script>

键盘 key

  • 用户按下的键盘键的值
  • 现在不提倡使用keyCode
    1. //微博发布案例
    2. // 文本域
    3. let textarea = document.querySelector("textarea");
    4. // 获取发布按钮
    5. let btn = document.querySelector("button");
    6. // 放置发布内容的div
    7. let content = document.querySelector(".content")
    8. // 点击发布将文本域内容插入到div中
    9. btn.addEventListener('click', function() {
    10. content.innerHTML = `${textarea.value}`
    11. if ((textarea.value.trim()) == '') {
    12. console.log('不输出');
    13. return
    14. }
    15. })
    16. // 当键盘按下将文本域内容插入到div中
    17. textarea.addEventListener('keydown', function(event) {
    18. if (event.key == "Enter") {
    19. btn.click()
    20. }
    21. })
    22. </script>

元素位置-三大家族

Web API - 图6

client家族

获取宽高
  1. clientWidth 获取可视区域的宽度(不包含滚动条)
  2. clientHeight 获取可视区域的宽度(不包含滚动条)

获取位置
  1. clientLeft 获取左边框的大小(只读属性)
  2. clientTop 获取上边框的大小(只读属性)
  3. resize 会在窗口尺寸改变的时候触发事件 resize window来绑定
    1. window.addEvenlistener('resize',function(){
    2. //执行的代码
    3. })
    1. const clientDom = document.querySelector('.client');
    2. // 宽度和高度
    3. console.log(clientDom.clientWidth); // 不包含 滚动条(类似 scrollWidth)
    4. console.log(clientDom.clientHeight); // 不包含 滚动条(类似 scrollHeight)
    5. // 获取边框的大小
    6. console.log(clientDom.clientLeft); // 左边框
    7. console.log(clientDom.clientRight);// 不能获取,没有clientRight
    8. console.log(clientDom.clientTop); // 上边框

offset家族

  1. 获取元素距离自己**定位父级**元素的左、上距离
  2. offsetLeft和offsetTop,是只读属性
  3. 获取元素的自身宽高、包含元素自身设置的宽高、padding、border
  4. offsetWidth/offsetHeight获取容器宽度和高度,包含滚动条的大小
    • offsetWidth
    • offsetHeight
  5. offsetTop/offsetLeft 获取当前元素距离,定位了的父元素的大小(找不到定位了的父元素,相对于页面来计算)
    • offsetLeft 获取定位了的父元素的 水平距离 左
    • offsetTop 获取定位了的父元素的 垂直距离 上
      1. //某个元素的
      2. let box1 = document.querySelector(".box1");
      3. console.log(box1.offsetWidth);//获取可视区域宽度,不包含滚动条
      4. console.log(box1.offsetHeight);
      5. console.log(box1.offsetLeft);//获取已经定位了的父级元素的左距离
      6. console.log(box1.offsetTop);

scroll家族

  • scrollTop
  • scrollLeft
  • scrollWidth
  • scrollHeight
  • Web API - 图7

页面滚动
  1. 监听整个页面滚动:
  1. window.addEventListener("scroll", function() {
  2. console.log(`页面滚动距离顶部${document.documentElement.scrollTop`};
  3. console.log(`页面滚动距离左边${document.documentElement.scrollLeft`};
  4. })

获取元素滚动距离

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

  1. dom.scrollTop 属性可修改
  2. dom.scrollLeft 属性可修改
  1. // 获取元素滚动的距离
  2. let div = document.querySelector("div");
  3. div.addEventListener("scroll", function() {
  4. console.log(`距离顶端的距离是${div.scrollTop}`);
  5. console.log(`距离左边的距离是${div.scrollLeft}`);
  6. })

获取高度和宽度
  • 获取元素的内容总宽高(包含padding,不包括margin、border)(不包含滚动条)返回值不带单位
  1. 整个可以滚动的区域的高度 scrollHeight (包含滚动的区域)
  2. 整个可以滚动的区域的宽度 scrollWidth (包含滚动的区域)
  1. let box = document.querySelector(".box");
  2. box.addEventListener("scroll", function() {
  3. console.log(box.scrollHeight); //获得滚动高度(包含padding,不包括margin、border)(不包含滚动条)
  4. console.log(box.scrollWidth); //获得滚动宽度(不包含滚动条)
  5. })

滚动条大小
  1. pc端滚动条大小占17px
  2. 移动端滚动条不占大小

案例

  1. //滚动一定高度,nav固定定位在顶部
  2. <style>
  3. * {
  4. margin: 0;
  5. padding: 0;
  6. box-sizing: border-box;
  7. }
  8. header {
  9. height: 250px;
  10. background-color: yellow;
  11. }
  12. nav {
  13. background-color: orange;
  14. height: 150px;
  15. }
  16. .fixed {
  17. position: fixed;
  18. left: 0;
  19. top: 0;
  20. width: 100%;
  21. }
  22. div {
  23. /* height: 150vh; */
  24. background-color: aqua;
  25. }
  26. </style>
  27. </head>
  28. <body>
  29. <header></header>
  30. <nav></nav>
  31. <div>
  32. <h1>1</h1>
  33. <h1>2</h1>
  34. <h1>3</h1>
  35. <h1>4</h1>
  36. <h1>5</h1>
  37. <h1>6</h1>
  38. <h1>7</h1>
  39. <h1>8</h1>
  40. <h1>9</h1>
  41. <h1>10</h1>
  42. <h1>11</h1>
  43. <h1>12</h1>
  44. 。。。。
  45. </div>
  46. <script>
  47. // 需求: 当页面滚动到一定的高度 nav变成了固定定位
  48. // 1 一定高度 其实就是header标签的高 250px
  49. // 步骤:
  50. // 1 需要在页面滚动距离 大于或者等于 250 的高时候
  51. // 1 设置nav标签做一个 固定定位
  52. // 2 否则就取消固定定位
  53. // 3 小bug 因为 nav标签做固定定位,不再拥有高度,自然把下面的标签给挡住!!!
  54. // 解决它
  55. // 给nav上面的标签 header标签 添加下外边距,大小 等于 nav的高
  56. const nav = document.querySelector('nav');
  57. const header = document.querySelector('header');
  58. window.addEventListener('scroll', function() {
  59. // 获取页面滚动的高度
  60. const scrollTop = document.documentElement.scrollTop;
  61. // 判断页面滚动高度
  62. if (scrollTop >= 250) {
  63. nav.classList.add('fixed');
  64. header.style.marginBottom = 150 + 'px';
  65. } else {
  66. nav.classList.remove('fixed');
  67. header.style.marginBottom = 0;
  68. }
  69. });
  70. </script>
  1. //点击图片回到最顶部
  2. <style>
  3. body {
  4. height: 200vw;
  5. background-image: linear-gradient(black, skyblue, pink);
  6. }
  7. a {
  8. position: fixed;
  9. right: 0;
  10. bottom: 50px;
  11. width: 100px;
  12. height: 100px;
  13. background-color: #fff;
  14. /* display: none; */
  15. cursor: pointer;
  16. background-image: url(http://md.zbztb.cn/uploads/454095101142/gotop.png);
  17. background-size: 100%;
  18. }
  19. a:hover {
  20. background-image: url(http://md.zbztb.cn/uploads/454095101142/gotop.gif);
  21. }
  22. </style>
  23. </head>
  24. <body>
  25. <a href="javascript:;"></a>
  26. <script>
  27. let a = document.querySelector("a")
  28. window.addEventListener('scroll', function() {
  29. // 获取页面滚动的高度
  30. const scrollTop = document.documentElement.scrollTop;
  31. // 判断页面滚动高度
  32. if (scrollTop >= 800) {
  33. a.style.display = "block"
  34. } else {
  35. a.style.display = "none"
  36. }
  37. });
  38. a.addEventListener('click', function() {
  39. let timeId = setInterval(function() {
  40. document.documentElement.scrollTop -= 10
  41. // 如果滚动高度等于0则关闭定时器
  42. if (document.documentElement.scrollTop == 0) {
  43. clearInterval(timeId)
  44. }
  45. }, 10)
  46. })
  47. </script>

事件流

描述

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

例:

  1. 假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段
  2. 简单来说:
  3. 捕获阶段是 从父到子。
  4. 冒泡阶段是 从子到父

Web API - 图8

阻止默认冒泡

  1. 因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素。
  2. 若想把事件就限制在当前元素内,就需要阻止事件流动。
  3. 阻止事件流动需要拿到事件对象。
    1. 事件对象.stopPropagation()
  1. 事件对象.preventDefault(),可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效。

阻止默认行为

  1. event.preventDefault()

例子

  1. a标签的点击跳转
    • return false也可以实现超链接阻止默认行为的效果,`但是return false后面的代码将不被执行。阻止默认行为 - form表单 有一个 submit 事件 不放置type=submit的按钮,回车不会提交表单。
    • 推荐使用 event.preventDefault()
  2. 阻止form表单 button默认行为
    • 给button按钮 添加一个 type = “button”。
    • 换成 input标签 type = “button”。
    • 把button 移出form表单的区域。
  1. a.addEventListener("click", function(event) {
  2. console.log("a标签的点击触发啦");
  3. // 阻止a标签的默认行为,让他不要跳转
  4. event.preventDefault();
  5. })
  6. form.addEventListener("submit", function(event) {
  7. // 不要让页面再刷新
  8. event.preventDefault();
  9. })

鼠标经过事件

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

注册事件的区别

传统on注册(L0)

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

事件监听注册(L2)

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

事件委托

  1. 优点:给父级元素加事件(可以提高性能)
  2. 原理:事件委托其实是利用事件冒泡的特点, 给父元素添加事件,子元素可以触发
  3. 实现:事件对象.target 可以获得真正触发事件的元素
  4. 案例
    1. <ul>
    2. <li>1
    3. <span>span</span>
    4. </li>
    5. <li>2</li>
    6. <li>3</li>
    7. <li>4</li>
    8. </ul>
    9. <script>
    10. let ul = document.querySelector("ul");
    11. // event.target 有可能是ul标签, 有可能是li标签, 还有可能是 a标签
    12. ul.addEventListener('click', function(event) {
    13. // event.target 当前点击的是哪个标签(点击最深最底层的那个标签即可)
    14. event.target.style.backgroundColor = 'skyblue';
    15. // 获取到被点击的标签
    16. console.log(event.target);
    17. })
    18. </script>

Window对象

Web API - 图9

BOM(浏览器对象模型)

  1. window 是浏览器内置中的全局对象,我们所学习的所有 Web APIs 的知识内容都是基于 window 对象实现的
  2. window 对象下包含了 navigator、location、document、history、screen 5个属性,即所谓的 BOM (浏览器对象模型)
  3. document 是实现 DOM 的基础,它其实是依附于 window 的属性。
  4. 注:依附于 window 对象的所有属性和方法,使用时可以省略 window

定时器

  1. setInterval()函数可以重复调用一个函数,在每次调用之间具有固定的时间间隔
  2. 定时器返回的是一个id数字

开启定时器

  1. setInterval(函数名字,间隔时间) //函数名字不需要加括号
  2. setInterval(function() {
  3. console.log('hhh');
  4. }, 1000)

每隔一段时间调用这个函数,间隔时间是毫秒。

关闭定时器

  1. let 变量名 = setInterval(函数,间隔时间)
  2. clearInterval(变量名)

延时器

  1. setTimeout()函数可以设置一个延时器,当指定时间到了 之后,会执行函数一次,不再重复执行。
  2. 平时省略window

开启延时器

  1. setTimeout(函数名字,间隔时间) //函数名字不需要加括号
  2. setTimeout(function() {
  3. console.log('hhh');
  4. }, 1000)

用延时器实现定时器的效果

  1. // 延时器不主动清除,定时器可以一直执行
  2. // 延时器只会执行一次
  3. // 延时器实现定时器功能
  4. // 在延时器又开启延时器,延时器又再开启延时器,延时器又再开启延时器
  5. let num = 0
  6. // 递归自己调用自己
  7. function fun() {
  8. console.log(++num);
  9. setTimeout(fun, 1000)
  10. };
  11. fun();

清除定时器

  1. clearTimeout()函数

Js执行机制

location对象

  • location 的数据类型是对象,它拆分并保存了 URL 地址的各个组成部分
  • 常用属性和方法:
    1. href 属性获取完整的 URL 地址,对其赋值时用于地址的跳转
    2. search 属性获取地址中携带的参数,符号 ?后面部分
    3. hash 属性获取地址中的啥希值,符号 # 后面部分
    4. reload 方法用来刷新当前页面,传入参数 true 时表示强制刷新
  1. <button>跳转</button>
  2. <script>
  3. //http://127.0.0.1:5500/7location.html
  4. let btn = document.querySelector("button");
  5. btn.addEventListener('click', function() {
  6. console.log(location.href); //目的:点击刷新 解决:让location.href等于当前页面location.href=location.href
  7. // location.href = 'http://127.0.0.1:5500/7-location.html'
  8. console.log(location.hash); //获取hash值 #号后面的字符
  9. // http://127.0.0.1:5500/7-location.html#/indes 输出 #/indes
  10. console.log(location.search); //获取问好后面字符 输出 a=2&b=23
  11. //http://127.0.0.1:5500/7-location.html?a=2&b=23
  12. })
  13. </script>

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

navigator对象

  1. navigator的数据类型是对象,该对象下记录了浏览器自身的相关信息
  2. 常用属性和方法:

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

  1. // 检测 userAgent(浏览器信息)
  2. !(function () {
  3. const userAgent = navigator.userAgent
  4. // 验证是否为Android或iPhone
  5. const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)
  6. const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)
  7. // 如果是Android或iPhone,则跳转至移动站点
  8. if (android || iphone) {
  9. location.href = 'http://m.itcast.cn'
  10. }
  11. })()

histroy对象

  1. history 的数据类型是对象,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
  2. 常用属性和方法:
    | history对象方法 | 作用 | | —- | —- | | back() | 可以后退功能 | | forward() | 可以前进功能 | | go(参数) | 前进后退功能都可以,例如参数是 1代表前进一个页面,-1代表后退一个页面 |
  1. <a href="https://www.baidu.com/">百度</a>
  2. <button class="btn1">前进</button>
  3. <button class="btn2">后退</button>
  4. <script>
  5. let btn1 = document.querySelector(".btn1")
  6. let btn2 = document.querySelector(".btn2")
  7. btn1.addEventListener('click', function() {
  8. history.forward()
  9. history.go(1)
  10. })
  11. btn1.addEventListener('click', function() {
  12. history.back()
  13. history.go(-1)
  14. })

本地储存

  1. 数据存储在用户浏览器中
  2. 设置、读取方便、甚至页面刷新不丢失数据
  3. 容量较大,sessionStorage和localStorage约 5M 左右

localStorage

  1. 生命周期永久生效,除非手动删除,否则关闭页面也会存在
  2. 可以多窗口(页面)共享(同一浏览器可以共享)
  3. 键值对的形式存储使用

存储数据

  1. localStorage.setItem(key, value)

获取数据

  1. localStorage.getItem(key)

删除数据

  1. localStorage.removeItem(key)
  1. //存 localStorage.setItem(key,value);
  2. //取 localStorage.getItem(key);
  3. //删除一个 localStorage.removeItem(key);
  4. //清空 localStorage.clear();
  5. // 生成一百个本地存储数据
  6. for (let i = 0; i < 100; i++) {
  7. localStorage.setItem(`abc${i}`, i)
  8. }
  9. // 清空所有本地存储
  10. // localStorage.clear();

存储复杂数据类型存储

  1. 本地只能存储字符串,无法存储复杂数据类型.需要将复杂数据类型转换成JSON字符串再存储到本地
  2. 本地存储存储复杂类型、引用类型的数据 ,会出现数据丢失的问题

JSON.stringify(复杂数据类型)
  • 将复杂数据转换成JSON字符串 ,存储 本地存储中

JSON.parse(JSON字符串)
  • 将JSON字符串转换成对象 , 取出 时候使用
  1. // console.log( localStorage.getItem("sdfdfdd") );// 如果没有数据的时候 本地存储会返回什么?
  2. // let str= localStorage.getItem("sdfdfdd");// null
  3. // JSON.parse(null)// 不正确了呀
  4. // 判断有没有数据 如果没有数据 返回一个空数组
  5. // 有数据 将字符串 解析成数组 再返回
  6. 对象 数组
  7. // localStorage.setItem('test', 123);
  8. // const test = localStorage.getItem('test');
  9. // console.log( typeof test ); // string
  10. // const obj = { name: '路飞' };
  11. // localStorage.setItem('obj', obj); // 存了一个对象数据进去 写法不对了
  12. // const newObj = localStorage.getItem('obj');
  13. // console.log(newObj);
  14. // 数组和对象 适合管理 比较复杂的数据
  15. // const obj = `{ name: '路飞', height: 100, weight: 200 }`;
  16. // // 丧失 对象 简洁用法的意义
  17. // console.log(obj.name );
  18. // console.log(obj.height );
  19. // console.log(obj.weight );
  20. // 把对象格式转成 字符串格式,继续使用 本地存储
  21. // localStorage.setItem("obj",obj);// obj 是一个长得像 对象的 字符串
  22. // 在行业中我们会这么做
  23. // // 1. 还是正常定义对象
  24. // const obj = {
  25. // name: '路飞',
  26. // height: 100,
  27. // weight: 200,
  28. // };
  29. // 2. 把一个对象转成字符串
  30. // const objStr = JSON.stringify(obj);
  31. // 3. 本地存储 可以存储字符串类型的数据
  32. // localStorage.setItem("obj",objStr);
  33. // 4. 把本地存储的数据重新读取出来
  34. // const newObjStr = localStorage.getItem("obj");
  35. // // console.log(newObjStr);
  36. // 5. 重新把这个字符串解析成原来的对象
  37. // const newObj = JSON.parse(newObjStr);
  38. // console.log(newObj);
  39. /*
  40. 1 本地存储无法存放 复杂类型的数据
  41. 2 复杂类型的数据 通过JSON对象 字符串 相互之间的转换
  42. */

sessionStorage

1、生命周期为关闭浏览器窗口

2、在同一个窗口(页面)下数据可以共享

3.以键值对的形式存储使用

4.用法跟localStorage 基本相同

5.会话(打开页面到关闭页面的一次会话 ,在ajax、node)存储

6.登陆的时候可能会用

  1. // 存
  2. sessionStorage.setItem('name', 123);
  3. // 取
  4. sessionStorage.getItem('name');
  5. // 删除一个
  6. sessionStorage.removeItem('name');
  7. // 清空
  8. sessionStorage.clear();

自定义属性

固有属性

  1. 标签天生自带的属性 比如class id title等, 可以直接使用点语法操作

自定义属性

  1. 由程序员自己添加的属性,在DOM对象中找不到, 无法使用点语法操作,必须使用专门的API
  2. 获取自定义属性
    1. getAttribute('属性名')
    2. getAttribute(key)
  1. 设置自定义属性
    1. setAttribute('属性名', '属性值')
    2. setAttribute(key,value)
  1. 删除自定义属性
    1. removeAttribute('属性名')
    2. removeAttribute(key)

data-自定义属性

  1. 传统的自定义属性没有专门的定义规则,开发者随意定值,不够规范,所以在html5中推出来了专门的data-自定义属性 在标签上一律以data-开头
  2. 在DOM对象上一律以dataset对象方式获取
    1. // 自定义属性 -> h5建议的自定义属性
    2. // 属性的时候 data-xxx 开头
    3. // 获取的时候 a.dataset.xxx
    4. // 设置 a.dataset.index = 3;
  1. <a data-index="0" id="nav" href="http://www.baidu.com" hello="no" aa="bb" >跳转</a >
  2. console.log( a.getAttribute("data-index") );
  3. console.log( a.getAttribute("id") );
  4. console.log( a.getAttribute("href") );
  5. console.log( a.getAttribute("hello") );
  6. console.log( a.getAttribute("aa") );

自定义属性案例

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no" />
  6. <title>13-自定义属性使用演示.html</title>
  7. <style>
  8. * {
  9. margin: 0;
  10. padding: 0;
  11. box-sizing: border-box;
  12. }
  13. </style>
  14. </head>
  15. <body>
  16. <ul></ul>
  17. <script>
  18. // 根据数组 渲染出li标签 点击li标签的时候 根据它对应的颜色 设置到 我body标签背景中
  19. // 数组
  20. let arr = [{
  21. price: '100',
  22. title: '去旅游',
  23. color: 'yellow'
  24. }, {
  25. price: '200',
  26. title: '去读书',
  27. color: 'red'
  28. }, {
  29. price: '300',
  30. title: '去吃饭',
  31. color: 'blue'
  32. }, ];
  33. const ul = document.querySelector('ul');
  34. let html = ``;
  35. for (let index = 0; index < arr.length; index++) {
  36. html += `<li data-price="${arr[index].price}" data-color="${arr[index].color}" >${arr[index].title}</li>`;
  37. }
  38. ul.innerHTML = html;
  39. // 事件委托
  40. ul.addEventListener('click', function(event) {
  41. // 当前点击的是li标签
  42. if (event.target.nodeName === 'LI') {
  43. // 设置body标签的背景颜色 等于什么 = 等于当前被点击的元素(li) 身上的自定义属性 data-color
  44. // document.body.style.backgroundColor = event.target.dataset.color;
  45. document.body.style.backgroundColor =
  46. event.target.getAttribute('data-color');
  47. // alert(
  48. // // `你想要去做的事情,要花这么多钱哦 ${event.target.dataset.price}`
  49. // );
  50. }
  51. });
  52. </script>
  53. </body>
  54. </html>

属性补充知识点

  1. setAttribute removeAttribute 可以获取到任意的属性(固有属性和h5建议的自定义属性)

字符串

  1. 转大写 toUpperCase()
  2. 转小写 toLowerCase()

排他思想

案例

  1. <ul>
  2. <li>我是li标签</li>
  3. <li>我是li标签</li>
  4. <li>我是li标签</li>
  5. </ul>
  6. <script>
  7. //获取所有li标签
  8. let lis = document.querySelectorAll("li");
  9. //遍历所有li
  10. for (let i = 0; i < lis.length; i++) {
  11. //哪个li点击就让让所有的li恢复基础样式,再单独给自己设置样式
  12. lis[i].addEventListener('click', function() {
  13. for (let j = 0; j < lis.length; j++) {
  14. lis[j].style.backgroundColor = '#fff'
  15. }
  16. //单独给自己设置样式
  17. this.style.backgroundColor = 'red'
  18. })
  19. }
  20. </script>

案例

点名(定时器)

  1. <h1></h1>
  2. <button class="btn1">start</button>
  3. <button class="btn2">end</button>
  4. <script>
  5. let h1 = document.querySelector("h1");
  6. let btn1 = document.querySelector(".btn1")
  7. let btn2 = document.querySelector(".btn2")
  8. let arr = [11, 22, 43, 54, 56, 7, 77];
  9. let timeId;
  10. function intervalDo() {
  11. let i = Math.round(Math.random() * (arr.length - 1));
  12. h1.innerText = arr[i];
  13. // 不给return,就返回return undefined
  14. }
  15. btn1.addEventListener('click', function() {
  16. if (timeId !== undefined) {
  17. clearInterval(timeId)
  18. }
  19. // 开启定时器
  20. timeId = setInterval(intervalDo, 100)
  21. })
  22. // 清除定时器
  23. btn2.addEventListener('click', function() {
  24. clearInterval(timeId)
  25. })

删除广告

  1. <div>
  2. <p>去领红包</p>
  3. <img src="./images/gd.png" alt="">
  4. <span>×</span>
  5. </div>
  6. <script>
  7. let div = document.querySelector("div");
  8. let span = document.querySelector("span");
  9. span.addEventListener('click', function() {
  10. div.style.display = 'none'
  11. })
  12. </script>

全选反选

  1. <table>
  2. <tr>
  3. <th class="allCheck">
  4. <input type="checkbox" name="" id="checkAll" />
  5. <span class="all">全选</span>
  6. </th>
  7. <th>商品</th>
  8. <th>商家</th>
  9. <th>价格</th>
  10. </tr>
  11. <tr>
  12. <td>
  13. <input type="checkbox" name="check" class="ck" />
  14. </td>
  15. <td>小米手机</td>
  16. <td>小米</td>
  17. <td>¥1999</td>
  18. </tr>
  19. <tr>
  20. <td>
  21. <input type="checkbox" name="check" class="ck" />
  22. </td>
  23. <td>小米净水器</td>
  24. <td>小米</td>
  25. <td>¥4999</td>
  26. </tr>
  27. <tr>
  28. <td>
  29. <input type="checkbox" name="check" class="ck" />
  30. </td>
  31. <td>小米电视</td>
  32. <td>小米</td>
  33. <td>¥5999</td>
  34. </tr>
  35. </table>
  36. <script>
  37. // checked值为true代表选中状态
  38. let checkAll = document.querySelector("#checkAll");
  39. let checkboxList = document.querySelectorAll(".ck");
  40. // 监听事件,绑定点击,注册点击,订阅点击
  41. console.log(checkAll.checked)
  42. // 当全选框点击,循环遍历复选框
  43. checkAll.addEventListener("click", function() {
  44. for (let i = 0; i < checkboxList.length; i++) {
  45. // 设置每个复选框的值为全选框的选中状态
  46. checkboxList[i].checked = checkAll.checked;
  47. }
  48. });
  49. for (let i = 0; i < checkboxList.length; i++) {
  50. checkboxList[i].addEventListener('click', function() {
  51. // 全选按钮 Allchecked
  52. // 函数isAllchecked()判断是否达到了全选条件,赋值给全选按钮
  53. let Allchecked = isAllchecked();
  54. // 设置页面全选框的值为 Allchecked,如果Allchecked值为true自然为全选
  55. checkAll.checked = Allchecked
  56. });
  57. }
  58. // 函数判断
  59. function isAllchecked() {
  60. // 存放选中复选框状态的数量
  61. let checkedNum = 0;
  62. // 循环复选框
  63. for (let i = 0; i < checkboxList.length; i++) {
  64. // 判断复选框的选中状态
  65. if (checkboxList[i].checked) {
  66. // 选中就+1
  67. checkedNum++
  68. }
  69. }
  70. // 循环结束, 判断选中的复选框的数量和所有复选框的总长度
  71. // 如果全等,则表示全部选中,返回true
  72. if (checkedNum === checkboxList.length) {
  73. return true
  74. } else {
  75. return false
  76. }
  77. }
  78. </script>