刘俊凯 发表于 2024-6-21 12:56:46

7天夺目Web APIs——-Bom操作(理论+实战)(第五天)

一、window对象

1.1 window对象和bom的关系

首先理解dom和bom之间的关系 显然bom的范围比力大
https://img-blog.csdnimg.cn/direct/d2bb120dc023465db438fe7b1f884a5c.png
bom的全称为欣赏器对象模子
window是bom的核心对象,window内里有许多属性和方法,用于实现欣赏器与 JavaScript 代码之间的交互。作为 JavaScript 的全局对象,window 代表了整个欣赏器窗口,其引用的代码范围涵盖了欣赏器窗口内的所有内容。也即是:通过 window 对象及其属性和方法,JavaScript 代码可以访问和操作与欣赏器相干的各种功能,如欣赏器窗口的巨细、位置、导航、历史记录等,以及通过 DOM来操作页面上的 HTML 元素。因此,通过 JS代码,我们可以实现欣赏器窗口与页面内容的丰富交互。
   而且bom和dom之间的关联就是: bom的核心对象是window,windom对象中含有document属性,进而访问页面中的各种元素。
https://img-blog.csdnimg.cn/direct/016b96c4f00140b0b3f7d958a78af9b2.png
   一般html中的声明变量、函数或者引用dom对象(dom元素)都是属于window的属性或者方法 window对象的所有属性和方法都可以省略window
<script>
      console.log(document === window.document)
      function fn () {
            console.log('哈哈')
      }
      window.fn()
      //全局变量
      var num = 10
      console.log(window.num);
    </script>
下面讲的都是关于window的,但是都是省略window的
二、定时器——延时函数

2.1 定时器定义和使用

   定义:让代码延迟一段时间执行的函数,叫做setTimeout
语法:setTimeout(回调函数,期待的毫秒数)
案例:五秒钟图片定时消失:
<img src="./images/ad.png" alt="">
    <script>
      setTimeout(function () {
            document.querySelector('img').style.display = 'none'
      }, 5000)
    </script>
2.2 两种定时器区别

dom中的setInterval 延时函数 相当于定时炸弹 到时间爆炸 并且只会爆炸一次
bom中的setTimeout 间歇函数 相当于上课铃 隔一段时间就会响
三、 js执行机制——单线程+eventloop

js语言的一大特点是单线程 也就是同一时间只能答应一件事情发生 这样做的利益是js的任务主要是为了处置惩罚页面的一些交互,例如 如果存在增加和删除,此时一定需要单线程。但是也存在js代码执行太慢的标题,例如以下案例:
答案是11 33 22
<script>
      console.log(11)
      setTimeout(function () {
            console.log(22)
      }, 3000)
      console.log(33);
    </script>
   按照js单线程的特性,应该是11 22 33 ,这里就要用到同步 异步的概念
同步:就是按部就班 一步步来 比如 一定是先洗菜 再炒菜
此时如果有煮饭,煮饭需要耗时,但是我们可以在这段耗时的过程中洗菜炒菜 两不耽搁 这里用到了异步 的过程
也就是同步就是一步步来,异步就是涉及到耗时
我们把一步步执行的(也就是同步)放在执行栈中,把耗时执行的放在任务队列中。
先执行执行栈中的同步任务,当时间够了,再将任务队列中的异步任务依次按序拿出到执行栈执行 https://img-blog.csdnimg.cn/direct/a58f7e88b7c4488da62b4a2960e633ee.png
也就是存在同步任务和异步任务的情况下,会先执行同步任务,并且将异步任务由欣赏器进行检测,当发现时间到了或者变乱要发生了,就会将任务拿到任务队列中,js会不停检测任务队列中有没有变乱,进而会变成主线程获取任务,执行任务,在获取任务 在执行任务。这种机制称为变乱循环 (event loop)
https://img-blog.csdnimg.cn/direct/bee62dc0dc0a46798f15a5306548428f.png
四、location对象

4.1 location重要属性 href 用于负值并进行地址的跳转

案例:实现五秒钟之后自动跳转
这里有一个标题需要注意:我们需要在a标签中提前写上5秒钟,这样便于一执行 出现在页面上的代码就是从5秒钟开始体现,否则因为js是从num–,那么从4秒钟开始体现。
<a href="#">支付成功<span>5</span>秒钟之后跳转到首页</a>
    <script>
      const a = document.querySelector('a')
      let num = 5
      setInterval(function () {
            num--
            a.innerHTML = `支付成功<span>${num}</span>秒钟之后跳转到首页`
            if (num === 0) {
                location.href = 'https://www.baidu.com/'
            }
      }, 1000)
    </script>
4.2 使用location.search 来获取?后面的东西

在讲表单信息提交给新地址时,一定要加上name属性
https://img-blog.csdnimg.cn/direct/d30880663a7d419cb99afd31d1fa9975.png
4.3 location.hash 来得到在不跳转新地址时,点击的链接 获取的是符号#后面部分

怎么才气知道点击的是哪一个选项 使用location.hash
https://img-blog.csdnimg.cn/direct/28c7c2d2201d42c3b3b1f3659346333d.png
4.4 reload方法

因为是方法,所以使用时必须加上小括号
   location.reload()革新页面 ;location.reload(true)强制革新页面
代替欣赏器革新按钮按钮
<button class="reload">刷新</button>
    <script>
      const reload = document.querySelector('.reload')
      reload.addEventListener('click', function () {
            // 刷新
            // location.reload()
            // 强制刷新
            location.reload(true)
      })
    </script>
五、navigator对象

如果检测到是手机端就会实现自动跳转
<script>
      // 检测 userAgent(浏览器信息)
      !(function () {
            const userAgent = navigator.userAgent
            // 验证是否为Android或iPhone
            const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)
            const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)
            // 如果是Android或iPhone,则跳转至移动站点先转换成移动端就会自动检测到移动端 然后完成跳转
            if (android || iphone) {
                location.href = 'https://www.baidu.com/'
            }
      })()
    </script>
https://img-blog.csdnimg.cn/direct/8291c5aeff05474d8bfcfdbd44ecde88.png
六、history对象

进步退却
    <button>后退</button>
    <button>前进</button>
    <script>
      const back = document.querySelector('button:first-child')
      const forward = back.nextElementSibling
      back.addEventListener('click', function () {
            // history.back()
            history.go(-1)
      })
      forward.addEventListener('click', function () {
            // history.forward()
            history.go(1)
      })
    </script>
七、本地存储

7.1 本地存储的定义和使用

就是将欣赏器作为仓库来保存数据,但实际上谁保存在用户电脑上(本地),并且革新数据不会丢失。除非手动删除。
特点:可以实现多页面共享数据(同一欣赏器)以键值对的情势进行存储 通过关键字localStorage
本地存储分类:
   但是需要注意无论是键还是值,都必须加上引号
<script>
      存储数据:
      localStorage.setItem('name', 'uname')
      获取数据:
      localStorage.getItem('name')
      删除数据:
      localStorage.removeItem('name')
    </script>
https://img-blog.csdnimg.cn/direct/76cad667be8a4342aba799ea07560334.png
7.2 本地存储分类- sessionStorage

用法同localStorage 只是实用于同一窗口 革新不会消失 但是更换窗口数据不会存在
7.3 存储复杂数据类型

在这里有一个标题:那就是本地只能存储字符串类型,不能存储复杂数据类型,例如:对象、数组。
请看案例:
<script>
      const good = {
            name: '小米',
            price: 999
      }
      localStorage.setItem('obj', good)
      console.log(localStorage.getItem('obj'));
    </script>
由效果就可以看出来:本地只能存储字符串类型,不能识别对象
https://img-blog.csdnimg.cn/direct/e221a9a5edb8434587bc305b3d9f5e64.png
7.4 转换成JSON字符串的语法

所以这里引入到将复杂数据类型(如:对象、数组)转化为JSON字符串类型,在存储到本地
   语法:JSON.stringify(复杂数据类型)
<script>
      const good = {
            name: '小米',
            price: 999
      }
      localStorage.setItem('obj', JSON.stringify(good))
      console.log(localStorage.getItem('obj'));
    </script>
这里又有一个标题,因为我们存储的时候,将复杂数据类型转化为了字符串存储,所以我们在使用本地数据的时候需要将数据重新转化为复杂数据数据类型
解决:把取出来的字符串转换为对象
   语法:JSON.parse(JSON字符串)
<script>
      const good = {
            name: '小米',
            price: 999
      }
      localStorage.setItem('obj', JSON.stringify(good))
      // 将JSON字符串转化为对象
      console.log(JSON.parse(localStorage.getItem('obj')))
    </script>
7.5 map和join方法

map方法 返回的是一个数组 这里参数是匿名函数 但是注意:匿名函数中的两个参数,index在下面的例子中没有什么作用,利用ele来实现字符串拼接
其中ele参数表示每一个数组元素
<script>
      const arr = ['red', 'blue', 'pink']
      const newArr = arr.map(function (ele, index) {
            return ele + '颜色'
      })
      console.log(newArr)
      // 字符串是黑色的
      console.log(JSON.stringify(newArr))
      console.log(arr.join(''))
      console.log(newArr.join('|'));
    </script>
   在这里,我本身有个标题,我在想要打印map方法时,没有在内里加上匿名函数就打印,爆出underfined:对此的理解是:对于一些方法不需要参数,此时可以打印到效果;对于一些方法需要参数,如果没有参数就打印
就会说未定义或者报错
增补:一般的字符串拼接:利用加号实现字符串拼接
<script>
      const x = '我' + '是' + '你'
      console.log(x);
    </script>
八、综合案例:学生信息表

需求:录入学生信息,并且数据不丢失**
模块分析:
8.1. 新增数据模块:输入学生信息 会自动存放到本地存储中

具体做法是:
localStograge本地存储 保证页面革新不丢失数据,但是大概导致存在已有数据,所以第一步:先找本地存储看是否有数据,有数据的话就渲染到页面;没有数据的话,放一个空数组,用来存放数据。
// 这里使用到了对象数组,因为只有在数组中才方便增加和删除
      const initData = [
            {
                stuId: 1001,
                uname: '欧阳霸天',
                age: 19,
                gender: '男',
                salary: '20000',
                city: '上海',
                time: '2099/9/9 08:08:08'
            }
      ]
      // 因为数据已经填写到本地存储 就不需要重复了反而会覆盖写的内容
      // console.log(localStorage.setItem('data', JSON.stringify(initData)))
      // 获取本地数据
      const data = localStorage.getItem('data')
      console.log(data)
      // 读取数据,如果是空数据就返回空数组;若果有数据就把对象数组返回 arr数组获得的是本地存储的数据
      const arr = data ? JSON.parse(data) : []
      // console.log(arr);
8.2 渲染模块,

数据会渲染到页面中 遍历数组,td内里填写对应td数据,并追加给tbody
具体内容是:


[*]遍历数组,td内里填写对应的td数据,并追加给tbody;
[*]使用map方法遍历数组,直接返回整个tr,内里包罗所有的tr标签,内里更换数据
[*]但是map方法返回的是对象数组,数组内里是tr,所以数组内里是字符串,所以我们通过join方法转换为字符串
[*]把返回的效果通过innerHTML赋值给tbody
   // 渲染模块函数
      const tbody = document.querySelector('tbody')
      function render () {
            const trArr = arr.map(function (ele, index) {
                // console.log(item)
                // console.log(item.uname)
                // 利用map遍历数组 返回对应tr的数组遍历一个对象返回一个对应tr的对象
                return `<tr>
                  <td>${ele.stuId}</td>
                  <td>${ele.uname}</td>
                  <td>${ele.age}</td>
                  <td>${ele.gender}</td>
                  <td>${ele.salary}</td>
                  <td>${ele.city}</td>
                  <td>${ele.time}</td>
                  <td>
          <a href="javascript:" data-id=${index}>
            <i class="iconfont icon-shanchu"></i>
            删除
          </a>
      </td>
            </tr>`
            })
            // 数组中的元素是字符串
            console.log(trArr)
            // 将tr数组转化为字符串
            tbody.innerHTML = trArr.join('')
            document.querySelector('.title span').innerHTML = arr.length
      }
      render()
8.3. 录入模块

具体做法是:


[*] 变乱是提交变乱,因为提交是使用form表单,在出现name属性的时候,就会出现默认提交变乱,所以需要克制默认提交变乱;
[*] 非空判断,获取所有需要填写的表单,他们的共同特点是都含有name属性;
[*] 遍历这些表单,如果有一个值为空,则return返回提示输入为空停止步调
[*] 只管淘汰dom操作,所以此处我们不在使用创建节点,追加结点方式。
核心步调:给arr数组追加对象,内里存储表单获取过来的数据;然后渲染页面和重置表单
这里需要注意的是:我们在录入数据的时候,表单输入没有id,但是渲染页面有,我们需要再录入的时候就添加,这样渲染页面的时候直接从本地取数据就可以了!
   stuId: arr.length ? arr.stuId + 1 : 1,
arr.push,是从最后追加,所以先找到最后一个子元素,在盘算id,因为是根据数组长度来盘算,那么当长度为0,很显然,stuId为1
// 录入模块
      const info = document.querySelector('.info')
      const uname = document.querySelector('.uname')
      const age = document.querySelector('.age')
      const gender = document.querySelector('.gender')
      const city = document.querySelector('.city')
      const salary = document.querySelector('.salary')
      //获取表单form里面带有name属性的元素
      const items = info.querySelectorAll('')
      info.addEventListener('submit', function (e) {
            //阻止默认提交
            e.preventDefault()
            //非空判断
            if (!uname.value || !age.value || !salary.value) {
                return alert('输入内容不能为空')
            }
            // 给arr数组追加对象里面存储从表单获取的数据
            // 后追加 拿着原来的数组长度+1
            arr.push(
                stuId: arr.length ? arr.stuId + 1 : 1,
                   // 为什么html中的元素都可以直接使用 那是因为只要我们通过js获取就可
                uname: uname.value,
                age: age.value,
                gender: gender.value,
                salary: salary.value,
                city: city.value,
                //当前日期对象
                time: new Date().toLocaleString()
            })
            render()
            this.reset()
            // 把数据传到本地存储 并且转换为字符串
            localStorage.setItem('data', JSON.stringify(arr))
      })
8.4. 删除模块

点击删除按钮,会删除对应数据,本地存储的数据也要删除
//删除业务
      // 采用事件委托的形式给tbody注册点击事件 因为是有新增 不方便给每个子元素注册所以采用
      tbody.addEventListener('click', function (e) {
            if (e.target.tagName === 'A') {
                if (confirm('您确定要删除这条数据哦')) {
                  arr.splice(e.target.dataset.id, 1)
                }
                render()
                localStorage.setItem('data', JSON.stringify(arr))
            }
      })
8.5 增补知识:arr.map的运行机制跟for循环机制

   arr.map的运行机制跟for循环机制等同
    <script>
      const arr = [
            {
                uname: 'glxx',
                age: 18
            },
            {
                uname: 'ghh',
                age: 18
            }
      ]
      // for (let i = 0; i < arr.length; i++) {
      //   console.log(arr.uname)
      // }
      //每次选取一个元素
      const newArr = arr.map(function (ele) {
            console.log(ele.uname)
      })
    </script>
8.6 完整代码

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>学生信息案例</title>    <link rel="stylesheet" href="css/index.css" /></head><body>    <h1>新增学员</h1>    autocomplete="off" input 的属性autocomplete 默以为on   其含义代表是否让欣赏器自动记录之前输入的值    <form class="info" autocomplete="off">      姓名:<input type="text" class="uname" name="'uname">      年龄:<input type="text" class="age" name="'age">      性别:<select name="gender" class="gender">            <option value="男">男</option>            <option value="女">女</option>      </select>      薪资:<input type="text" class="salary" name="salary">      就业城市:      <select name="city" class="city">            <option value="上海">上海</option>            <option value="厦门">厦门</option>            <option value="广州">广州</option>            <option value="深圳">深圳</option>            <option value="曹县">曹县</option>            <option value="河南">河南</option>      </select>      <button class="add">录入</button>    </form>    <h1>就业帮</h1>    <div class="title">共有数据<span>0</span>条</div>    <table>      <thead>            <tr>                <th>学号</th>                <th>姓名</th>                <th>年龄</th>                <th>性别</th>                <th>薪资</th>                <th>就业城市</th>                <th>录入时间</th>                <th>操作</th>            </tr>      </thead>      <tbody>            <!--         <tr>          <td>1001</td>          <td>欧阳霸天</td>          <td>19</td>          <td>男</td>          <td>15000</td>          <td>上海</td>          <td>            <a href="javascript:">删除</a>          </td>      </tr>         -->      </tbody>    </table>    <script>      // 这里使用到了对象数组,因为只有在数组中才方便增加和删除
      const initData = [
            {
                stuId: 1001,
                uname: '欧阳霸天',
                age: 19,
                gender: '男',
                salary: '20000',
                city: '上海',
                time: '2099/9/9 08:08:08'
            }
      ]
      // 因为数据已经填写到本地存储 就不需要重复了反而会覆盖写的内容
      // console.log(localStorage.setItem('data', JSON.stringify(initData)))
      // 获取本地数据
      const data = localStorage.getItem('data')
      console.log(data)
      // 读取数据,如果是空数据就返回空数组;若果有数据就把对象数组返回 arr数组获得的是本地存储的数据
      const arr = data ? JSON.parse(data) : []
      // console.log(arr);
      // 渲染模块函数      const tbody = document.querySelector('tbody')      function render () {            const trArr = arr.map(function (ele, index) {            //打印也并不是自顾自的想要打印就打印,如果是在函数中,必须函数调用了才气打印                // console.log(item)                // console.log(item.uname)                // 利用map遍历数组 返回对应tr的数组遍历一个对象返回一个对应tr的对象                return `<tr>                  <td>${ele.stuId}</td>                  <td>${ele.uname}</td>                  <td>${ele.age}</td>                  <td>${ele.gender}</td>                  <td>${ele.salary}</td>                  <td>${ele.city}</td>                  <td>${ele.time}</td>                  <td>          <a href="javascript:" data-id=${index}>            <i class="iconfont icon-shanchu"></i>            删除          </a>      </td>            </tr>`            })            // 数组中的元素是字符串            console.log(trArr)            // 将tr数组转化为字符串            tbody.innerHTML = trArr.join('')            document.querySelector('.title span').innerHTML = arr.length      }      render()      // 录入模块      const info = document.querySelector('.info')      const uname = document.querySelector('.uname')      const age = document.querySelector('.age')      const gender = document.querySelector('.gender')      const city = document.querySelector('.city')      const salary = document.querySelector('.salary')      //获取表单form内里带有name属性的元素      const items = info.querySelectorAll('')      info.addEventListener('submit', function (e) {            //克制默认提交            e.preventDefault()            //非空判断            if (!uname.value || !age.value || !salary.value) {                return alert('输入内容不能为空')            }            // 给arr数组追加对象内里存储从表单获取的数据            // 后追加 拿着原来的数组长度+1            arr.push({                // 为什么html中的元素都可以直接使用 那是因为只要我们通过js获取就可以了                stuId: arr.length ? arr.stuId + 1 : 1,                uname: uname.value,                age: age.value,                gender: gender.value,                salary: salary.value,                city: city.value,                //当前日期对象                time: new Date().toLocaleString()            })            render()            this.reset()            // 把数据传到本地存储 并且转换为字符串            localStorage.setItem('data', JSON.stringify(arr))      })      //删除业务
      // 采用事件委托的形式给tbody注册点击事件 因为是有新增 不方便给每个子元素注册所以采用
      tbody.addEventListener('click', function (e) {
            if (e.target.tagName === 'A') {
                if (confirm('您确定要删除这条数据哦')) {
                  arr.splice(e.target.dataset.id, 1)
                }
                render()
                localStorage.setItem('data', JSON.stringify(arr))
            }
      })
    </script></body></html>
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 7天夺目Web APIs——-Bom操作(理论+实战)(第五天)