DOM01


DOM: document object model 文档对象模型
浏览器中输入 window - document 对象
浏览器提供的API: window.document 对象

网页的HTML代码是如何运行到浏览器上的?

  • 浏览器解析HTML文本代码, 转化成 对象类型 – window.document
  • 然后 把这个 document对象类型, 渲染到页面上
  • 所以: 页面真正显示的是 document 这个对象类型
  • 利用 document 对象, 就可以直接操作浏览器的界面
    在这里插入图片描述

01-初识DOM

<!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>初识DOM</title>
  </head>
  <body>
    <!-- 
      原始状态: 只需要 DOM 和 浏览器就能展现网页
      但是DOM是JS的代码, 书写繁琐 且 不易读
      所以提供了HTML这种标签语言, 便于用户书写网页代码

      但是HTML只能完成简单的DOM操作, 更加复杂的浏览器操作还是需要原生DOM才能实现

      实际上运行: HTML -> DOM对象 -> 显示在浏览器
     -->
    <h1>Hello DOM</h1>

    <script>
      // 浏览器利用 检查->元素 中, 就是document对象 美化之后的样子
      // log: 会对打印的内容自动美化, 而非原本的模样
      console.log(document) //document 就是DOM对象
      // dir: direct 直接, 才能打印出真正样子
      console.dir(document) //cdi

      // DOM树: 一个形象的比喻, 讲述的是 HTML 如何转化成DOM对象
    </script>
  </body>
</html>

DOM树

// DOM树: 一个形象的比喻, 讲述的是 HTML 如何转化成DOM对象
在这里插入图片描述

DOM总结

在这里插入图片描述

常见元素获取-head,body,html

<!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>常见元素</title>
  </head>
  <body>
    <!-- 当HTML转化成DOM时, 有一些固定的元素/节点 
      1. html整体
      2. head
      3. body
    -->
    <h1>Hello DOM</h1>

    <script>
      console.log(document.head)
      console.dir(document.head)

      console.log(document.body)
      console.dir(document.body)

      // html标签
      console.log(document.documentElement)
      console.dir(document.documentElement)
    </script>
  </body>
</html>

自定义节点获取

<!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>自定义节点</title>
  </head>
  <body>
    <!-- 
      DOM操作一共分两个步骤:
      1. 查找你要操作的元素
      2. 操作这个元素
     -->
    <div>1111</div>
    <div>2222</div>
    <div>3333</div>

    <script>
      // 查找元素的方式非常多, 选择合适的
      // 1. 根据与已知元素间的关系查找
      // 已知 body 节点,  找其第一个子元素

      // firstChild: 第一个孩子
      console.log(document.body.firstChild) //基本不用

      // firstElementChild: 第一个 元素类型 的孩子
      console.log(document.body.firstElementChild)

      // 最后一个元素类型的孩子:
      console.log(document.body.lastElementChild)

      // 所有孩子
      console.log(document.body.children)

      // 获取孩子中的具体某一个, 利用序号
      console.log(document.body.children[2])
      // item(序号):  由于比 [序号] 麻烦, 所以大家不爱用
      console.log(document.body.children.item(2))
    </script>
  </body>
</html>

自定义元素查找

id方式

<!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>通过id查找</title>
  </head>
  <body>
    <div></div>
    <div>
      <div>
        <!-- id: 唯一标识, 要求不重复 -->
        <span id="s1">Hello World</span>
        <span>Hello World</span>
      </div>
    </div>
    <div></div>

    <script>
      // 通过id查找指定元素
      // get:获取 Element:元素 By:通过 Id:唯一标识
      console.log(document.getElementById('s1'))

      // 简化操作: id太常用了, 所以系统会自动完成:
      // var id名 = document.getElementById(id名)
      console.log(s1)

      // 不推荐使用, 两个原因:
      // 1. 读代码时, 会不知道变量哪里来的 -- 团队合作不合适(开发时,代码向下兼容)
      // 2. 浏览器兼容性, 低版本没有这个自动操作
    </script>
  </body>
</html>

标签方式

<!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>
  </head>
  <body>
    <div>
      <div>
        <span>11</span>
      </div>
      <div>
        <span>22</span>
      </div>
    </div>

    <script>
      // 注意:  elements  带s 代表复数, 因为同名标签可以有多个
      // get:获取 Elements:元素们 By: 通过 Tag:标签 Name
      console.log(document.getElementsByTagName('span'))
    </script>
  </body>
</html>

name方式

<!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>
  </head>
  <body>
    <div>
      <!-- 单标签闭合写法  <单标签 />  -->
      <!-- 在H5中, 官方推荐省略 <单标签>, 例如 <br> -->
      <!-- 但是 在后续的一些框架中,推荐闭合 -->
      <input type="radio" name="sex" id="" />
      <span></span>
      <br />
      <input type="radio" name="sex" id="" />
      <span></span>
    </div>

    <script>
      // 通过 name 属性获取:  名字可重复,所以是多个
      // elements : s结尾代表复数
      console.log(document.getElementsByName('sex'))
    </script>
  </body>
</html>

class方式

<!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>
  </head>
  <body>
    <div class="danger">111</div>
    <div>222</div>
    <div class="danger">333</div>

    <script>
      // 通过 class 名查找
      console.log(document.getElementsByClassName('danger'))
    </script>
  </body>
</html>

通过css选择查找

querySelector返回满足条件的第一个元素(node),而querySelectorAll返回满足条件的所有元素(nodelist);
2.在都没有满足条件的元素情况下:querySelector返回null,而querySelectorAll返回空的数组[]。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>通过css选择器查找</title>
  </head>
  <body>
    <div id="left">left</div>
    <div id="right">right</div>
    <div class="jump">
        <a href="">百度</a>
    </div>
    <script>
      var div = document.querySelector('div');
      console.log(div);

      var div = document.querySelectorAll('div');
      console.log(div);

      var d = document.querySelector('.jump>a');
      console.log(d);
    </script>
  </body>
</html>

通过关系查找

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>关系型选择器</title>
  </head>
  <body>
    <div class="box">
      <div class="bro">
        <h1>电影名称</h1>
      </div>
      <div class="msg">
        <h2>这么多年</h2>
        <h2>速度与激情10</h2>
      </div>
      <h3>花海</h3>
      <h3>黑色毛衣</h3>
    </div>
    <script>
      // 父选子
      var box = document.querySelector('.box');
      console.log(box.children);

      // 子选父
      var msg = document.querySelector('.msg');
      console.log(msg.parentNode);
      console.log(msg.parentElement);
      // 选第一个子元素
      console.log(msg.firstElementChild);
      //   选最后一个子元素
      console.log(msg.lastElementChild);
      //   选上一个兄弟
      console.log(msg.previousElementSibling);
      //   选下一个兄弟
      console.log(msg.nextElementSibling);
    </script>
  </body>
</html>

操作style - 把id='d2’的文字颜色改为红色

<!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>
  </head>
  <body>
    <div></div>
    <div>
      <div>1111</div>
      <div id="d2">2222</div>
      <div>3333</div>
    </div>
    <div></div>

    <script>
      // 1.找到id='d2' 的元素
      let d2 = document.getElementById('d2')
      console.log(d2)
      console.dir(d2)
      // 2.修改其样式, 变红
      d2.style.color = 'red'
        
	  //给每一个子元素添加边框
        
      // parent: 父母
      let d2_p = d2.parentElement
      console.log(d2_p)
      // children: 所有子元素
      let divs = d2_p.children
      console.log(divs)
      // 伪数组类型, 没有forEach方法, 用 for..of遍历
      for (let el of divs) {
        // el: 是element 元素的缩写, 可以随意起名
        el.style.border = '1px solid blue'
      }
    </script>
  </body>
</html>

事件

所有的DOM事件参考: 所有DOM事件链接

https://www.runoob.com/jsref/dom-obj-event.html

<!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>事件</title>
  </head>
  <body>
    <div>
      <button>点我</button>
    </div>

    <script>
      // 注意: 伪数组元素 , 要通过 `序号` 来获取具体的元素
      let btn = document.getElementsByTagName('button')[0]
      console.log(btn)
      // 所有的事件都是用 on 开头的, 这是一个明显的标识
      // HTML DOM事件: https://www.runoob.com/jsref/dom-obj-event.html
      console.dir(btn)

      // onclick: 点击
      // onclick时 触发函数, 不应该写箭头函数, 因为this的指向问题
      // 箭头函数this: 指向声明时所在作用域,此处是window
      // 普通函数: 运行时所在对象, 此处是btn
      btn.onclick = function () {
        console.log('this:', this)
        // 点击后 为按钮的父元素添加边框
        this.parentElement.style.border = '1px solid red'
      }
    </script>
  </body>
</html>

实战练习-点击显示下拉框

<!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>
      .menu {
        padding: 4px;
        background-color: antiquewhite;
        width: 200px;
        /* 双击选中文本: 不开启此功能 */
        user-select: none;
      }
      /* +: 兄弟选择器, 代表 .menu 下方的div */
      .menu + div {
        display: none;
      }
    </style>
  </head>
  <body>
    <div>
      <div class="menu">菜单</div>
      <div>
        <div>黄焖鸡</div>
        <div>盖浇饭</div>
        <div>鸭血粉丝汤</div>
        <div>肯德基</div>
      </div>
    </div>

    <script>
      // 1. 选择 class='menu' 的元素
      let menu = document.getElementsByClassName('menu')[0]
      console.dir(menu)
      // 2. 添加点击事件
      menu.onclick = function () {
        // 3. 点击后,把其下方的兄弟元素, display:'block'
        // next:下一个 Element:元素 Sibling:兄弟姐妹
        // style: 优先级比 class选择器高, 所以覆盖class中的 display:none 效果
        //this.nextElementSibling.style = 'block'
        
        let style = this.nextElementSibling.style
        // style:是对象类型, 地址传递, 引用类型
        // 内联样式: 默认值是空字符串
        if (style.display == '') {
          style.display = 'block'
        } else {
          style.display = ''
        }

        // 错误写法:  display是普通数据类型 ''
        // 类似于: let a = 5; let b = a; b=10; a变不变
        // a不变: 普通数据类型是值传递, 是独立的变量
        // let display = this.nextElementSibling.style.display
        // display = ''
      }
    </script>
  </body>
</html>

升级-每个菜单点击后, 都能实现 展开/收起(XXX)

<!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>
      .menu {
        margin-top: 2px;
        padding: 4px;
        background-color: antiquewhite;
        width: 200px;
        /* 双击选中文本: 不开启此功能 */
        user-select: none;
      }
      /* +: 兄弟选择器, 代表 .menu 下方的div */
      .menu + div {
        display: none;
      }
    </style>
  </head>
  <body>
    <div>
      <div class="menu">菜单1</div>
      <div>
        <div>黄焖鸡</div>
        <div>盖浇饭</div>
        <div>鸭血粉丝汤</div>
        <div>肯德基</div>
      </div>
      <div class="menu">菜单2</div>
      <div>
        <div>黄焖鸡</div>
        <div>盖浇饭</div>
        <div>鸭血粉丝汤</div>
        <div>肯德基</div>
      </div>
      <div class="menu">菜单3</div>
      <div>
        <div>黄焖鸡</div>
        <div>盖浇饭</div>
        <div>鸭血粉丝汤</div>
        <div>肯德基</div>
      </div>
    </div>

    <script>
      // 任务: 每个菜单点击后, 都能实现 展开/收起
      // 提示: 查询所有 class='menu',  for..of 遍历为每个添加点击事件 即可
      let menus = document.getElementsByClassName('menu')
      console.log(menus)

      for (let menu of menus) {
        menu.onclick = function () {
          let style = this.nextElementSibling.style
          // 空字符串代表: 没有 style.display 样式
          style.display = style.display == '' ? 'block' : ''
        }
      }
    </script>
  </body>
</html>

操作class

<!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>操作class</title>
    <style>
      .box {
        width: 200px;
        height: 200px;
        border: 1px solid red;
        /* 样式变化时的动画时长 */
        transition: 0.25s;
      }
      /* 一会通过按钮进行切换 */
      .abc {
        background-color: purple;
        border-radius: 50%;
      }
    </style>
  </head>
  <body>
    <button>添加样式</button>
    <button>移除样式</button>
    <button>切换样式</button>
    <div id="box" class="box ab xy ui ww"></div>

    <script>
      let btns = document.getElementsByTagName('button')
      console.log(btns)
      let box = document.getElementById('box')

      //添加
      btns[0].onclick = function () {
        //样式操作有两种: className  和 classList
        // className: 此方式直接操作class='' 的值, 比较简陋
        // box.className = 'box abc'

        // classList: 提供了简单操作class的各种方法
        // add(): 在原有元素基础上, 添加新的
        box.classList.add('abc')
      }
      //移除
      btns[1].onclick = function () {
        // remove: 删除
        box.classList.remove('abc')
      }
      //切换
      btns[2].onclick = function () {
        // toggle: 切换 -- 有->删; 没有->加
        box.classList.toggle('abc')
      }
    </script>
  </body>
</html>

class实战 - 菜单添加动画

<!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>
      #menu {
        width: 200px;
        border: 1px solid gray;
      }
      .title {
        background-color: bisque;
        padding: 5px;
        margin-top: 2px;
      }
      .title + div {
        transition: 1s;
        /* 最大高度: 支持动画,  height:auto;不支持 */
        max-height: 0;
        overflow: hidden;
      }
      /* 显示: 高度改成自动 */
      /* div.show: div标签 同时代表 show样式 */
      div.show {
        max-height: 150px;
      }
    </style>
  </head>
  <body>
    <div id="menu">
      <div class="title">菜单1</div>
      <div>
        <div>红烧牛肉</div>
        <div>老坛酸菜</div>
        <div>鲜虾鱼板</div>
        <div>香辣牛肉</div>
      </div>
      <div class="title">菜单2</div>
      <div>
        <div>红烧牛肉</div>
        <div>老坛酸菜</div>
        <div>鲜虾鱼板</div>
        <div>香辣牛肉</div>
      </div>
    </div>

    <script>
      // 选择 class='title' 元素
      let titles = document.getElementsByClassName('title')
      console.log(titles)

      for (let title of titles) {
        title.onclick = function () {
          // toggle: 切换
          // nextElementSibling: 下一个兄弟元素
          this.nextElementSibling.classList.toggle('show')
        }
      }

      // 点击事件: 切换 class='show' 样式
    </script>
  </body>
</html>

页数指示器

<!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>
      .indicator {
        width: 400px;
        padding: 5px 0;
        text-align: center;
        background-color: lightgray;
      }
      .indicator > span {
        display: inline-block;
        width: 16px;
        height: 16px;
        background-color: white;
        border-radius: 50%;
      }
      .indicator > span.cur {
        background-color: deepskyblue;
      }
    </style>
  </head>
  <body>
    <!-- indicator: 指示器 -->
    <div class="indicator">
      <!-- cur: 是 current 缩写, 当前项的意思 -->
      <span class="cur"></span>
      <span></span>
      <span></span>
      <span></span>
    </div>

    <script>
      // 所有 小圆点:  class='indicator' 元素下的所有子元素
      // let points = document.getElementsByClassName('indicator')[0].children

      // 实战中: 通常使用 css 选择器, 最万能 最准确
      // querySelectorAll: all 查询多个满足条件的
      let points = document.querySelectorAll('.indicator>span')
      // 这种用法: 结果的原型中, 有forEach可以用
      points.forEach(value => {
        // onmouseover: 鼠标悬浮时触发
        value.onmouseover = function () {
          // 找到之前带有 .cur 样式的元素, 删除样式
          // 通过css选择器查找元素, 必须要预判结果的数量
          // 此处预判到结果只有一个, 所以:
          // querySelector: 结果是单个元素
          let span_cur = document.querySelector('.cur')
          console.log('span_cur:', span_cur)
          span_cur.classList.remove('cur')

          console.log(this)
          // 鼠标悬浮时, 添加 cur 样式
          this.classList.add('cur')
        }
      })

      console.log(points)
    </script>
  </body>
</html>

页数

<!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>
      .pages {
        background-color: lightgray;
        padding: 5px;
        width: 400px;
        text-align: center;
        user-select: none;
      }
      .pages > span {
        display: inline-block;
        width: 30px;
        height: 30px;
        line-height: 30px;
        background-color: white;
        color: deepskyblue;
        border-radius: 4px;
      }
      .pages > span:hover,
      .pages > span.cur {
        color: white;
        background-color: deepskyblue;
      }
    </style>
  </head>
  <body>
    <div class="pages">
      <span class="cur">1</span>
      <span>2</span>
      <span>3</span>
      <span>4</span>
      <span>5</span>
    </div>

    <script>
      // document.querySelector    查单个
      // document.querySelectorAll 查多个, forEach遍历

      let spans = document.querySelectorAll('.pages>span')
      console.log(spans)

      spans.forEach(span => {
        // 参数名:span, 看起来更加容易理解, 比value更有含义
        span.onclick = function () {
          // 移除之前高亮元素的 cur
          let span_cur = document.querySelector('.pages .cur')
          span_cur.classList.remove('cur')
          // 为当前点击的添加cur
          this.classList.add('cur')
        }
      })
    </script>
  </body>
</html>



菜单 - 不简化

<!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>
      #menu {
        /* 软件: snipaste 截图 屏幕标记 取色器 */
        background-color: rgb(0, 44, 105);
        color: white;
        user-select: none;
      }
      #menu > span {
        display: inline-block;
        width: 100px;
        padding: 5px 0;
        text-align: center;
      }
      #menu > span.cur {
        background-color: orange;
      }
    </style>
  </head>
  <body>
    <div id="menu">
      <span class="cur">首页</span>
      <span>关于净美仕</span>
      <span>公司动态</span>
      <span>产品中心</span>
      <span>联系我们</span>
    </div>

    <script>
      const qsa = document.querySelectorAll('#menu>span')
      console.log(qsa);
      
      // 推荐用const 代替 let , 因为更安全, 变量没有变更需求的场景
      qsa.forEach(value => {
        value.onclick = function () {
          //删除之前高亮的
          const qs = document.querySelector('#menu .cur')
          qs.classList.remove('cur')
          this.classList.add('cur')
        }
      })
    </script>
  </body>
</html>

练习

<!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>
      #menu {
        user-select: none;
      }
      #menu > span {
        display: inline-block;
        padding-bottom: 5px;
        margin: 0 10px;
        color: gray;
        font-size: 2em;
      }
      #menu > .cur {
        font-weight: bold;
        color: black;
        border-bottom: 5px solid blue;
      }
    </style>
  </head>
  <body>
    <div id="menu">
      <span class="cur">账号登录</span>
      <span>短信登录</span>
    </div>

    <script>
 	  const qsa = document.querySelectorAll('#menu span')
      qsa.forEach(value => {
        value.onclick = function () {
          const qs = document.querySelector('#menu .cur')
          qs.classList.remove('cur')
          this.classList.add('cur')
        }
      })
    </script>
  </body>
</html>

作业

作业1:

  • 悬浮状态 :hover , 只有非 当前项才有, 应该利用 :not 排除当前项
    • span:not(.cur):hover: span标签中, 不是.cur样式的元素,悬浮态
      在这里插入图片描述

作业2:

标签栏切换的头部: 点击之后的项目是白色背景
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值