Web前端第三阶段--DOM

Web前端第三阶段–DOM



DOM树

请添加图片描述


初识DOM

  • 整个HTML, 在浏览器上会被解析成 document 对象
  • 浏览器上最终显示的内容, 本质是个JS对象
  • 而 HTML 作为语法糖, 只能进行简单的页面配置
  • 学习DOM的目的: 抛开语法糖, 直接操作页面本身的 本质代码. 可以更加灵活的操作页面

DOM作用

  • DOM的重点作用: 弥补 HTML 不具备的能力 – 动态
 setInterval(() => {
      const a = new Date().toLocaleTimeString()
      console.log(a)
      // 目的: 把时间放在 id=time 的元素里打印
      // 1. 在脚本中, 如何得到 id=time 的元素的引用
      // DOM提供了一个 get获得 Element元素 By通过 Id标识
      const time = document.getElementById('time')
      console.log(time) // log: 美化后的
      console.dir(time) // dir: 直接输出对象 -- 本质
      // 展开, 找到 innerHTML -- inner内部的  HTML

      // 2. 如何修改其中的文本
      time.innerHTML = a
    }, 1000);

固定元素的读取

  • html文件中有3个标签是固定的, 必然会有
 	console.dir(document.head)
    console.dir(document.body)
    console.dir(document.documentElement) // 整个html
  • 操作元素的属性
    p0.onclick = function () {
      console.log('别碰我!!')
      // 样式操作有两种: 内联style 和 内部class
      this.style.color = 'red'
      // onclick在p0对象里, 所以 this就是p0
    }

标签读取元素

  • 查找指定名称的标签 Tag标签 Name名
  • 结果是 伪数组/类数组, 没有数组方法, 不能用forEach
    getElementsByTagName()

CSS选择器读取元素

    const tds1 = document.querySelectorAll('tr:first-child>td')
    console.log(tds1) //注意观察原型

    tds1.forEach(td => {
      console.log('正在为:', td, '绑定事件');
      td.onclick = function () {
        this.style.backgroundColor = 'red'
      }
    })

querySelectorAll
querySelector

class操作

 // 添加
    btn1.onclick = function () {
      box.className = 'yuan'
    }

    // 删除
    btn2.onclick = function () {
      // 把 box的className改为空
      box.className = ''
    }

    // 切换
    btn3.onclick = function () {
      // 判断: 如果是空的, 就改为yuan
      // if (box.className == '') {
      //   box.className = 'yuan'
      // } else {
      //   box.className = ''
      // }

      // 三目:
      box.className = (box.className == '' ? 'yuan' : '')
    }

classList

  • classList: 把class属性封装后得到的对象
    // 添加:
    btn1.onclick = function () {
      // add: 增加/添加 新的class值
      // 优点: 相较于自己修改className, 使用方法更加的安全可靠
      box.classList.add('yuan')
    }

    // 删除: remove
    btn2.onclick = function () {
      box.classList.remove('yuan')
    }

    // 切换: toggle
    btn3.onclick = function () {
      box.classList.toggle('yuan')
    }

简单实例

点击按钮头像发生变化

 // 点击按钮, 让头像发生变化
    const btns = document.querySelectorAll('button')
    const img = document.querySelector('img')
    console.dir(img) //查看其 src 属性

    // 箭头函数接收3个实参: 元素, 序号, 数组本身
    btns.forEach((btn, index) => btn.onclick = function () {
      // 问题: 如何判定事件是哪个按钮触发的?
      console.log('被点击:', index);

      const names = ['LeeSin', 'Gwen', 'Annie', 'Galio', 'Seraphine']
      // 模板字符串:  利用下标序号 读取对应的图片名, 拼接成路径
      img.src = `./heros/${names[index]}.png`

      // 序号0的按钮, 则图片的路径 = 
      // if (index == 0) img.src = './heros/LeeSin.png'
      // if (index == 1) img.src = './heros/Gwen.png'
      // if (index == 2) img.src = './heros/Annie.png'
      // if (index == 3) img.src = './heros/Galio.png'
      // if (index == 4) img.src = './heros/Seraphine.png'
    })

大小图切换效果

 <img src="./heros/Annie.jpg" alt="">
  <div id="heros">
    <img class="active" src="./heros/Annie.png" alt="">
    <img src="./heros/Galio.png" alt="">
    <img src="./heros/Zoe.png" alt="">
    <img src="./heros/Seraphine.png" alt="">
    <img src="./heros/Olaf.png" alt="">
  </div>

  <script>
    const heros = document.querySelectorAll('#heros>img')
    const img_big = document.querySelector('body>img')

    heros.forEach((hero, index) => hero.onmouseover = function () {
      heros.forEach(h => h.classList.remove('active'))

      hero.classList.add('active')

      // 让大图随着发生变化
      const names = ['Annie', 'Galio', 'Zoe', 'Seraphine', 'Olaf']
      // 修改大图的src
      img_big.src = `./heros/${names[index]}.jpg`
    })

轮播图

 const dians = document.querySelectorAll('#banner span')
    const imgs = document.querySelectorAll('#banner img')

    dians.forEach((dian, index) => dian.onmouseover = function () {
      dians.forEach(d => d.classList.remove('active'))
      this.classList.add('active')

      // 先删所有图的激活
      imgs.forEach(i => i.classList.remove('active'))
      // 通过小圆点的序号, 找到对应序号的图, 添加激活
      imgs[index].classList.add('active')

      // 例如: 悬浮在序号1的小圆点, 就会找到序号1的图, 让其激活
    })

轮播图(滑动)

 // DOM操作: 先找到你要操作的元素
    const dians = document.querySelectorAll('#banner span')
    const img_d = document.querySelector('#banner>div:first-child')

    dians.forEach((dian, index) => dian.onmouseover = function () {
      dians.forEach(d => d.classList.remove('active'))

      this.classList.add('active')
      // 根据小圆点的序号, 获得对应的偏移量
      const x = index * -400 // 400是图片宽度
      // 设置给图片的父
      img_d.style.transform = `translateX(${x}px)`
    })

自定义属性

const titles = document.querySelectorAll('#tabs>div:first-child>span')

    titles.forEach(title => title.onclick = function () {
      titles.forEach(t => t.classList.remove('active'))
      this.classList.add('active')

      // 需求: 选择不同的题目, 要激活对应的详情
      // 问题: 如何 把题目 和 详情关联在一起??

      // 读取点击项的 自定义属性 存储的id
      const id = this.dataset.id
      console.log("id:", id);
      // 通过id读取对应的详情元素
      const d = document.getElementById(id)
      // 排他:  自己.爸爸.儿子们 .  此写法查询出的元素, 没有forEach. 只能用for..of遍历
      for (const x of d.parentElement.children) {
        x.classList.remove('active')
      }

      d.classList.add('active')
    })


    //解释
    document.getElementById('bz')

    //等价:
    var id = 'bz'
    document.getElementById(id)

输入框事件

 const inp = document.querySelector('input')

    // 获得焦点 focus
    inp.onfocus = function () {
      console.log('onfocus: 获得焦点');
    }

    // 失去焦点 blur
    inp.onblur = function () {
      console.log('onblur: 失去焦点');
    }

    // 内容变化 change
    // 触发方式: 修改输入框内容 然后 回车 或 失去焦点
    inp.onchange = function () {
      console.log('onchange:内容变化');
      // 大多数 form 表单元素的 值, 都是 value 属性
      console.log(this.value)
    }

    // 内容实时变化 input
    inp.oninput = function () {
      console.log('input:', this.value);
    }

    // 键盘事件  keyup
    // 事件参数: 每个触发的事件, 都会接收一个实参, 即当前事件相关的信息
    inp.onkeyup = function (e) {
      // 形参名: 原则是见名知意,  event 习惯缩写 e
      console.log(arguments);
      console.log('按键抬起');
      // keyCode: 事件参数中的一个属性, 代表按键的 唯一编号
      // 例如 回车:13
      if (e.keyCode == 13) {
        alert("检测到回车, 开始登录...")
      }
    }


    // 使用场景:
    // 搜索栏 的实时搜索: 利用 input 事件, 例如 京东, 百度..
    // 

标签内容

  • innerHTML: 读取html代码, 写入时作为html解析
  • innerText: 读取文本 部分, 写入时作为纯文本展示

事件冒泡机制

  • 事件的冒泡机制: 当子元素上发生一个事件时, 会传递给其父元素
  • 阻止传播: 依赖事件参数的 stopPropagation 方法
  • 事件触发的当事元素: 事件的target属性
  • 用途: 事件委托模式下, 可以处理动态新增的子元素的事件
    const red = document.getElementById('red')
    red.onclick = function (e) {
      // 两个后代: 蓝色 和 绿色
      // 问题: 点蓝色 和 点绿色, 都会传播事件给 当前的红色区域
      // 如何分辨事件的当事元素是谁?
      console.log(e) //查看其target属性, 就代表触发事件的当事元素
      // 测试方式: 分别点击 绿 蓝 红 然后观察
      console.log('target:', e.target);

      console.log('red被点击');
    }

    const blue = document.getElementById('blue')
    blue.onclick = function () {
      console.log('blue被点击');
    }

    const green = document.getElementById('green')
    green.onclick = function (e) {
      // 事件参数: 作为事件触发时, 默认传递而来的. 包含了事件相关的各种API
      console.log('事件参数:', e);

      // stop:停止 propagation传播
      // e.stopPropagation() //阻止事件传播, 即 终止冒泡
      // 现象: 点击绿色后, 父元素不再收到点击事件

      console.log('green被点击');
    }

事件委托

const btn = document.querySelector('button')
    const ul = document.querySelector('ul')
    // 点击后, 在ul的结尾累加新的
    btn.onclick = function () {
      ul.innerHTML += '<li>良琴</li>'
      // 问题: 读取原字符串 拼接后, 得到全新的. 重新设置给ul的子元素
      // 我们之前添加过点击事件的 li, 都被替换掉了. 所以不能被点击
    }

    // 对于动态新增/变化的子元素: 可以给其父元素添加点击事件
    // 事件委托: 让父元素帮助子元素完成事件相关的操作
    ul.onclick = function (e) {
      console.log('ul: 接收到点击事件')
      console.log(e.target);
      // 委托的注意事项: 所有子元素 和 元素自身 都会触发事件, 我们必须分辨事件是 我们想要操作的元素, 再去做事
      // 例如: 此处只有 li 元素才应该被处理. 必须判定是li再做事
      console.dir(e.target)

      // 有3个属性 nodeName  tagName  localName 都是标签名
      // 注意大小写不同

      // 如果是 li 标签, 才变绿
      if (e.target.localName == 'li') {
        // 为当事元素添加样式
        e.target.style.color = 'green'
      }
    }


    // 要求: 点击li时, 让其文字变红
    // const lis = document.querySelectorAll('ul>li')

    // lis.forEach(li => li.onclick = function () {
    //   this.style.color = 'red'
    // })

阻止默认事件

  • preventDefault: 阻止 默认事件的发生
    // a标签 带有 href属性, 点击时会自动跳转页面
    // 希望: 为a标签添加点击事件 来代替默认的href跳转
    // 默认情况: 先触发onclick 再触发href跳转

    const a = document.querySelector('a')
    a.onclick = function (e) {
      // 事件参数: 含有各种操作事项的API
      // preventDefault: 阻止 默认事件的发生
      e.preventDefault()

      alert("超链接被点击")
    }

鼠标点击事件坐标

在这里插入图片描述

  const box = document.getElementById('box')

    let n = 1

    box.onclick = function (e) {
      // 防止点击span标签导致触发添加操作, 排除法
      if (e.target != box) return

      console.log(e) //去查看, 哪些属性, 代表点击事件发生的坐标
      const { offsetX, offsetY } = e

      const el = `<span style="left:${offsetX}px; top:${offsetY}px">${n++}</span>`

      this.innerHTML += el //拼接添加
    }

事件监听器

  • 多人协作开发, 如果使用onclick 方式绑定事件. 一旦两个人给同一个元素的onclick 绑定事件, 则出现冲突, 覆盖
  • 需求: 不会产生覆盖的, 可以同时绑定多个事件的 – 事件监听器
  • 两个参数: 事件名–不带on, 触发的函数

页面滚动事件

  • scroll: 滚动. 浏览器的页面滚动事件
 onscroll = function () {
      console.log('滚动中....');
      // 获取滚动的距离
      // 兼容性问题: 不同的浏览器 不同的版本, 读取偏移量有两种方案. 从两个方案中读取有值的那个
      const y = document.documentElement.scrollTop || document.body.scrollTop

      console.log('y:', y)

      // 目标: 当滚动距离 超过800就显示头, 否则就隐藏头
      if (y > 800) {
        header.classList.remove('hide')
      } else {
        header.classList.add('hide')
      }

      // 延伸知识: 每次滚动都进行判定, 过于频繁. 效果极大的系统性能
      // 利用 防抖与节流 技术可以 降低检测频率, 节约系统性能-- 面试常问
      // 看 百度网盘提供的扩展视频
    }

    // 逻辑或: 有真则真, 全假则假
    // 逻辑或的设定: 表达式的值 是从左到右的首个真值, 如果没有真值就是最后一个
    const a = 0 || '' || null || undefined || 66 || true
    console.log(a);

    const b = 0 || '' || null || undefined
    console.log(b)

    // 实际上, if判断的是 0 是真是假, 因为 逻辑或的结果是 0
    if (false || 0) { }

BOM

  • 用于操作浏览器上的各种属性

打开新页面

    // 场景: 先看5秒广告, 然后再跳转到页面
    <a href="http://tmooc.cn" target="_blank">Tmooc</a>
    <button onclick="go()">前往</button>
    、、、、、、、、、、、、、、、、
    const p = document.querySelector('p')
    let n = 5

    function go() {
      let t = setInterval(() => {
        p.innerHTML = '即将跳转' + n--
        if (n == 0) {
          clearInterval(t)
          // open: 可以打开新的页面
          // 参数1: 新页面的地址
          // 参数2: 打开方式, 默认是_blank 代表新的标签
          open("http://tmooc.cn", '_self') // _self:当前标签打开
          n = 5
        }
      }, 1000);
    }

地址栏操作

 console.log(location) //包含所有地址栏相关的信息

    // location的search中, 存储了URL传参的字符串
    // 需要利用固定的写法来读取
    // URLSearchParams: 把 字符串格式, 转为可操作的 对象类型
    const params = new URLSearchParams(location.search)
    // get: 获取.  可以从参数对象中, 获取指定名称的参数的值
    const page = params.get('page')
    console.log(page);

    // 根据路径的参数page 的值, 高亮不同的项目
    // 现在的触发方式: 点击超链接->刷新页面->自然会执行这里的代码
    const navs = document.querySelectorAll("#nav a")
    navs.forEach(n => n.classList.remove('active'))

    if (page == 'about') {
      navs[1].classList.add('active')
    }
    if (page == 'news') {
      navs[2].classList.add('active')
    }
    if (page == 'index' || page == null) {
      navs[0].classList.add('active')
    }

浏览器信息读取

alert(navigator.onLine ? '在线' : '没有网络')

    // platform: 浏览器运行的平台
    // Win32 代表windows
    // MacIntel 代表苹果

历史操作

  <!-- history的原型中提供了很多操作历史的方式, 其中的万能方法go 最好用 -->
  <!-- go(n): n是数字  0刷新 负数-后退  正数-前进 -->
  <button onclick="history.go(-1)">上一页</button>
  <button onclick="history.go(0)">刷新</button>
  <button onclick="history.go(1)">下一页</button>

  <!-- 点击进入, 点左上角返回,  再点下一页 -->
  <a href="http://tmooc.cn">Tmooc</a>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值