当前位置: 首页 > news >正文

WEB APIs day5

在这里插入图片描述在这里插入图片描述

一、window对象

BOM属于window对象
在这里插入图片描述

1.BOM(浏览器对象模型)

在这里插入图片描述
bom里面包含着dom,只不过bom我们平时用得比较少,我们经常使用的是dom操作,因为我们页面中的这些标签都是在dom中取的,所以我们操作dom多一点。
在这里插入图片描述
window对象里面dom是核心(document object model),当然window对象里面除了dom对象之外还有很多其它很多对象(如navigator(显示你用的什么浏览器的),location(location有很多的方法,比如说我们的可以通过js的形式跳转页面,下载xx的时候不用写个a,写一个普通盒子就行了,因为我们js也可以跳转页面,实现下载的功能的,通过js的方式跳转页面。因为我们有的情况下是让它自动跳转页面,比如说我注册成功了,我让它5s之后自动跳转到首页,是自动跳转,不需要a链接来点击),history(历史对象),screen(屏幕)。
最大的是window,其次是document。
alert其实是window.alert(),console.log其实是window.console.log()。基本上我们所有的对象都是基于window的,所以大多数情况下可以省略。
在这里插入图片描述

<!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>bom</title>
</head><body><script>// document.querySelector()// 按理说这个更合适,因为一层一层的去找,但是我们都知道window是最大的,没有比它更大的了,所以window是可以省略的 // window.document.querySelector()// 验证一下console.log(document === window.document)// 我们声明的这些函数或者全局变量,其实都挂在window上,我们调用的时候其实是window.fn()function fn() {console.log(11)}window.fn()// 我们全局声明的变量也是如此// var声明的是挂在window上,不是const,const不行// const num = 10// 所以var或者函数声明的这一些,默认都挂在window下,const和let就不是,因为它们是挂在自己的作用域内var num = 10console.log(window.num)</script>
</body></html>

2.定时器—延时函数

在这里插入图片描述
这个定时器和之前我们学的定时器interval不同,这个定时器只执行一次,(比如说弹出的一个小广告,显示几秒之后自动关闭,关闭之后就不再出来了),而之前学的定时器是一直执行的,(比如说轮播图)。第一个定时器是间歇定时器,间隔多少秒执行一次,而延时是多少秒之后执行一次,然后就不再执行了。和前面间歇函数的写法一模一样,只是名字和功能不一样而已。
定时器有两种,间歇(setInterval)和延时(setTimeout)
就执行一次为什么要清除?因为延时函数后面会有一些特殊的使用方法,它可以借助一种函数,叫递归函数,自己调自己可以来模拟定时器,但是自己调自己很容易把自己调晕,隔多少秒之后就来执行一次,执行完之后再回来调一次自己,又开始了。所以在特殊情况下我们需要清除。
平时我们只用一次的就不用去清除了,但是在某些特殊情况下,比如说setTimeout自己调自己,用到递归函数的时候我们就必须要清除了。这个后面会讲。
按道理,定时器都能开启和清除。setInteval返回的值是数字型的id(1、2…是第几个定时器),setTimeout返回的也是一个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>延时函数</title>
</head><body><script>// 到了2s之后打印1次之后就不会再继续打印了setTimeout(function () {console.log('时间到了')}, 2000)</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>5秒自动关闭的广告</title><style>img {position: fixed;left: 0;bottom: 0;}</style>
</head><body><img src="./images/ad.png" alt=""><script>// 1.获取元素  将图片获取过来const img = document.querySelector('img')// 2.开启定时器setTimeout(function () {img.style.display = 'none'}, 3000)</script>
</body></html>

3.JS执行机制

JS的执行机制:JS到底是怎么执行的。首先JS代码是从上往下执行的,第二,我们知道JS要解析,JS有JS解析器,浏览器有2个引擎,第一个引擎叫渲染引擎,可以渲染html,css,第2个引擎是用来解析JS的,叫JS解析器。在谷歌浏览器里面内置了一个V8引擎,是我们浏览器的一个,这个V8引擎是专门用来解析我们的JS的。
在这里插入图片描述
2个的结果都是1111,3333,2222
在这里插入图片描述
单线程有一个特点,比如说有一个元素,要进行删除操作,必须要先添加再删除,不能还没有就删除,不能同时进行添加和删除操作,这就是js的特点,从上往下依次执行,只能单线程不能多线程。单线程意味着我们所有的任务需要排队,前面一个任务结束后面一个任务才会进行,如果JS的执行时间过长,这样就会造成页面的渲染不连贯。
在这里插入图片描述
如果遇到上面那种耗时的操作,造成页面的阻塞,js有解决这个问题,利用了多核CPU的计算能力。JS本来是单线程的,但是我们为了解决这个问题,我们可以创建多个线程,所以这里JS出现了同步和异步。
在这里插入图片描述
定时器是异步任务,因为它是耗时的,哪怕是耗0s也是耗时的。耗时的任务都是异步任务,异步任务放在任务队列中的。(需要注意的是,我们JS是没有队列和栈的,只是借助其他语言的队列和栈来更好的理解我们这门语言)
在这里插入图片描述
什么是事件循环?(去面试一般都会问到)
就是整个执行栈里面执行完了之后,就去任务队列里面看,把任务队列里面的拿过来再执行,执行栈里面的这个异步任务执行完之后就又去任务队列里面拿,如果再有就再拿过来执行,反复这样转圈,就是一个循环。这个我们称之为事件循环。
在这里插入图片描述

<!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><script>console.log(1)console.log(2)setTimeout(function () {console.log(3)})console.log(4)</script>
</body></html>

JS是单线程的,没有办法处理多线程,但是浏览器可以处理多线程。
在这里插入图片描述
先把1放入执行栈,再把2放入执行栈,因为同步任务是立马就执行完的,所以先打印1,再打印2。这个点击和定时器都耗时,是异步任务,所以JS就不处理了,提交给浏览器处理,将这两个异步事件放到浏览器,浏览器实时监测是先点击还是时间先到,假如是时间先到,就提交给任务队列,执行栈在执行完同步任务之后就一直在等待,所以当在任务队列里面看到时间之后就先执行时间,如果一直没点击就不执行点击事件(1234)。如果在执行完1、2之后,发现先点击了,就先把点击推过去,然后执行栈再取过来执行,之后时间到了才是时间(1243)
在这里插入图片描述

4. location对象

在这里插入图片描述在这里插入图片描述

<!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>location</title>
</head><body><script>// console.log(window.location)// console.log(location)// console.log(location.href)// 不一定点链接让页面跳转,页面也可以自动跳转// 1. href 经常用href 利用js的方法跳转页面// 既然是属性,那我们就可以赋值// 最典型的一个使用场景是,当我注册成功之后,会提示5s之后自动跳转回首页(不需要点击,自动跳转,这是location.href的使用)location.href = 'http://www.baidu.com'</script>
</body></html>

在这里插入图片描述
这个经常见于注册一个账号,注册成功后几秒后自动跳转回首页,或者支付完之后多少秒跳转回首页。
我们应该用setInterval而不是setTimeout,因为里面的数字在变每隔1s就会换一次。
在这里插入图片描述

<!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>5秒钟之后自动跳转页面</title><style>span {color: red;}</style>
</head><body><a href="http://www.itcast.cn">支付成功<span>5</span>秒钟之后跳转到首页</a><script>// 1. 获取元素const a = document.querySelector('a')// 2. 开启定时器// 3. 声明倒计时变量let num = 5// timerId里面存的是一个序号 let timerId = setInterval(function () {num--// 上来之后会立即变成4吗?不会,因为定时器1s之后才会调用这些代码a.innerHTML = `支付成功<span>${num}</span>秒钟之后跳转到首页`// 倒计时成了0就应该跳转了,并且关闭定时器// timeId里面存的是序号// 如果num === 0 则停止定时器,并且完成跳转功能if (num === 0) {// 没有名字清除不了clearInterval(timerId)// 4. 跳转  location.hreflocation.href = 'http://www.itcast.cn'}}, 1000)</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>location属性和方法</title>
</head><body><!-- 表单一定要有name,不然提交不了数据 --><form action=""><input type="text" name="username"><input type="password" name="pwd"><button>提交</button></form><!-- 只有那一块变了,后面vue会学到 点击之后是my就把my显示过来,是friend就把friend显示过来 --><!-- 用哈希拿到#后面的值 知道是点的哪一个 --><a href="#/my">我的</a><a href="#/friend">关注</a><a href="#/download">下载</a><button class="reload">刷新</button><!--location 除了那些属性外,还有一个方法 --><script>const reload = document.querySelector('.reload')reload.addEventListener('click', function () {// 类似于按下F5 刷新页面// location.reload()// 强制刷新  ctrl+f5location.reload(true)})</script>
</body></html>

在这里插入图片描述

在这里插入图片描述
spa单页面应用程序,有很多都是一个页面,它只是其中一块变了,别的没变,上面没刷新。这种应用后面会学,因为它是一种非常好用的应用,因为它不需要刷新整个页面,加载资源就会比较少,这种应用页面没有变,它没有跳转页面就可以实现页面跳转,它的实现原理是它是通过#后面的值来发生变化来发生判断的,所以我们在获取的时候一定要拿到#后面的值,后面还会讲。我们可以通过哈希来拿到这个值。在这里插入图片描述
在这里插入图片描述
true强制执行,比如说有些网页上面的小图标,favicon已经引进来了,但是图标一直不出来,刷新也不管用,这时候可以ctrl+f5强制刷新,所谓强制刷新就是不从本地里面去取数据了,而是在线重新渲染重新拉下来这些数据
在这里插入图片描述在这里插入图片描述

5. navigator对象

在这里插入图片描述
比如京东的页面,PC端打开就是PC端,移动端打开就是移动端。
这个代码不需要我们写,正则都出来了,不用去背,要用的时候直接cv就行。
如果是手机端跳转到http://m.itcast.cn上去,如果是pc端就不跳转。
在这里插入图片描述

<!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><!-- 拿过来之后直接放在最上面就行了 --><!-- 这是立即函数加了一个! --><script>// 检测 userAgent(浏览器信息)!(function () {const userAgent = navigator.userAgent// 验证是否为Android或iPhoneconst android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)// 如果是Android或iPhone,则跳转至移动站点if (android || iphone) {// 只需要把它换成自己想要的地址就可以了location.href = 'http://m.itcast.cn'}})()// 写在上面也可以// 最后一个要加;// (function () { })();    这个前面加不加!无所谓// 还有人喜欢这么写:这样写是错误的,因为JS不会认为这是一个整体,它会认为是调用的一个function函数// function(){}()// 但是如果加一个!或者+或者~等等,只要是一个算术表达式都能的,它就会把前面当做一个整体了// !function () { }()</script>
</head><body>这是PC端的页面<!--  <script>// (function () { })()</script> -->
</body></html>

6. history对象

在这里插入图片描述在这里插入图片描述

<!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>history对象</title>
</head><body><button>后退</button><button>前进</button><script>const back = document.querySelector('button:first-child')// back的下一个兄弟const forward = back.nextElementSibling// 回调函数back.addEventListener('click', function () {// 后退一步// 怎样实现后退?复制有前进后退按钮的地址到一个页面中打开即可// history.back()// 单词难记,推出了更好记的方法history.go(-1)})forward.addEventListener('click', function () {// 前进一步// 要是前进不了是因为没有再打开一个新的页面,在前进后退按钮页面再打开另外一个地址// history.forward()history.go(1)// location.reload可以刷新页面})</script>
</body></html>

二、本地存储

在这里插入图片描述

1. 本地存储介绍

在这里插入图片描述
本地存储是一个仓库,用于存放数据,你可以理解为“数据库”,但是这个数据库比较特殊,是放在浏览器里面的。以前我们也有一个小仓库存放数据,叫变量,变量是放在内存的,内存有一个特点,一刷新就没了,但是有的数据我们不想丢失,所以我们在浏览器里面添加了一个小仓库,用于存放数据,只要浏览器在它就在,数据不会丢失。
本地存储一共有两个,sessionStorage和localStorage,每个都约5M左右。在这里插入图片描述https://todomvc.com/examples/vanilla-es6/在这里插入图片描述

2. 本地存储分类

在这里插入图片描述
大多数时候是可以共享的,当然也有不能的情况,当我们讲ajax的时候,它如果涉及到跨域的问题,是不能访问的,后面会讲。
在这里插入图片描述在这里插入图片描述在这里插入图片描述
另外打开一个页面,跟刚才的页面没有任何关系,发现有storage但是发现没有这些数据,原因是我们没有学过跨域,比如说京东和百度的数据肯定是不能共享的,他有不同的域名,前面的域名不相同是不能取的。当我们打开history对象这个代码的页面,F12点击storage(我们还没有讲跨域,讲了跨域之后就懂了)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述我们发现打印出的18是字符型的。由此可知,本地存储只能存储字符串数据类型,不管什么类型都给你转换成字符串类型。这个跟变量不一样。在这里插入图片描述
localStorage关闭浏览器不会消失,sessionStorage关闭浏览器就消失。和变量的区别是sessionStorage也是存到仓库里面去的,只不过它关闭浏览器就会消失。sessionStorage和localStorage的用法一致(存,获取,删除,改)。
在这里插入图片描述

<!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>localStorage存储</title>
</head><body><script>// 要存储一个名字 uname// 键值对要加引号,不加引号就当成变量来看了,是个字符串   //属性名 值localStorage.setItem('uname', 'pink老师')// 2. 获取方式  都加引号console.log(localStorage.getItem('uname'))// 3. 删除本地存储  只删除名字 (手动删除)// 能打印:因为是先存再打印最后再删除的// localStorage.removeItem('uname')// 4. 改   (如果原来有这个键,则是改,如果没有这个键则是增)localStorage.setItem('uname', 'black')// 我要存一个年龄   18不用加引号,因为是数字型localStorage.setItem('age', 18)// 除了数字型,其他的都要加引号// 实在记不住,全部都加上引号也行// 我们发现打印出的18是字符型的    由此可知,本地存储只能存储字符串数据类型,不管什么类型都给你转换成字符串类型console.log(localStorage.getItem('age'))// sessionStorage和localStorage的用法一致</script>
</body></html>

在这里插入图片描述

3. 存储复杂数据类型

在这里插入图片描述
一个一个地存太麻烦,考虑存对象或者数组的形式
在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述

<!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><script>const obj = {uname: 'pink老师',age: 18,gender: '女'}/* //存储 复杂数据类型// 第一个obj是键     第二个obj是值(因为是变量了所以就不加引号了)localStorage.setItem('obj', obj)   //直接采取这种格式我们得到的是[obj][obj]这种格式,为解决这个问题,我们把复杂数据类型转换成JSON字符串/*//这样也可,只不过上面那种更好localStorage.setItem('obj', {uname: 'pink老师',age: 18,gender: '女'})*/// 取 */// console.log(localStorage.getItem('obj'))// 不能像上面那么写   我们应该转换完了再存// 1. 复杂数据类型存储必须转换为JSON字符串存储// 因为要转换所以JSON.stringfy()是个方法// 这个代码会把对象转换为字符串存进去,也可以直接把obj里面的内容直接复制到方法的括号里面去localStorage.setItem('obj', JSON.stringify(obj))// 在本地存储里面只能存储字符串// 取// 打印出来是黑色的 所以是字符串而不是对象// console.log(localStorage.getItem('obj'))// 也可以检测一下是不是字符串console.log(typeof localStorage.getItem('obj'))// JSON对象  特点:属性和值有引号,而且引号统一是双引号// {"uname":"pink老师","age":18,"gender":"女"}   //看着像对象但它已经不是对象了,它是字符串// 我们取过来的是字符串,不能直接用,这样就拿不到数据(uname,age这些)了,那么反过来,我们把这个字符串转化成对象,以后就可以拿过来数据直接渲染了// 2. 把JSON字符串转换为对象// 先获取再转换console.log(JSON.parse(localStorage.getItem('obj')))/* // 如果觉得看起来挺费劲,可以这样const str = localStorage.getItem('obj')console.log(JSON.parse(str)) */</script>
</body></html>

三、综合案例在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

对象数组,因为数据有很多条,所以我们要把对象放到数组里面去
在这里插入图片描述
(2). 如果没有数据,则用 空数组来代替 的具体实施:
逻辑或中断,如果有数据就把数据存进去,返回的就是数组,数组不为空,那就是真的,根据逻辑或中断的原则,如果前面为真,则后面就不执行了,但是如果把本地存储里面的数据清空,那它里面就没有内容,没有内容就为空,空就是假,取出一个空字符串,根据逻辑或中断的原则,前面为假则执行后面的,那么就把后面的空数组返回过来了。
我们可以把存储数据注释起来看看效果。
根据本地存储的原则,即使已经注释起来了,但是刚才已经存过了,所以也有,我们可以把它清空,本地存储就没有数据了,重新刷新一下页面,再打开控制台,就会发现返回的是一个空数组,那说明我们写的程序是正确的,因为一会儿我们渲染页面,如果数组里面有数据,就根据数组里面的数据渲染页面,如果数组是空的,那么渲染的页面也就是空的页面。
在这里插入图片描述
前面我们已经拿到了数据,接下来我们根据数据渲染页面,比如说我有几条数据就可以在下面渲染几行
在这里插入图片描述
以前我们用字符串拼接str+=这种效率并不高,而我们以后的开发中利用的是map和join这两种数组方法来实现字符串拼接,这种的效率会更高一些,那么就意味着从今天开始以后所有的渲染页面拼接字符串统一使用数组的这两个方法来实现。因为这个方法需要以前拼接字符串str方式的铺垫,前面的学习了后面再学习这个会更简单。在这里插入图片描述
1.map的语法格式:map里面有一个回调函数,回调函数里面有2个参数,这个写法和for each很像,ele(element)是数组元素,index是数组索引号,只不过map在使用的时候可以添加下面这一句话:return ele + ‘颜色’,它的意思是让数组的每个元素进行添加颜色,每循环一次就把当前的结果返回过来,一共有3个数组元素所以循环了3次,那拼接完,map最大的特点是有返回值,返回新的数组,现在我们通过new arr把数组拿过来了,返回的就是把数据处理之后的结果,并且放到了一个数组里面。

2.map不仅可以遍历数组还可以处理数据,比如说可以让数组里的每一个数据拼接字符串,第一次循环让red加上颜色,第二次循环让blue加上颜色…每次循环都有一个返回值返回到了数组。它的本质是这样子:只要用到了map,它的返回值就是数组,先准备一个空数组,第一次循环就可以把red颜色返回过来,第二次循环就是blue颜色…,这样的话整个map执行完就会生成一个新的数组,然后我们就可以拿到这个数组了。
在这里插入图片描述
在这里插入图片描述
分析:我们前面已经能够拿到数据了 ,数组里面放着相关对象,然后我们可以根据里面有几条数据生成几个tr。我们可以这么去做,可以用map去遍历数组,看看有几个对象,然后根据对象去处理数据,也就是说可以生成tr,在生成tr的同时我们就就可以把拿到的数据的值放到相应的位置,也就是说我在生成tr的时候,把数据填充进去。第一次循环就生成一个tr,但是如果数组里面有多条数据,那么每次循环都有一个返回值放到数组里面去再生成第二个tr,所以map方法最大的特点就是可以生成对应数据的tr,然后再把数据填充进去。我们知道map方法最大的特点是有一个数组返回给我们,等到map全部遍历完了就根据你有几条数据返回对应的数组,所以map有一个数组返回给我们了,但是虽然里面有相应的tr了,它毕竟是个数组,我们没有办法把数组直接追加给tbody,所以我们还需要做一步,通过join的方法把数组转换成字符串,也就是说我们要的不是数组是字符串。我有2个tr全都连在一起就形成了一个字符串,我们最后就可以把这个字符串追加给tbody,有了这些tr页面之中就可以把它渲染出来了。这个就是我们说的通过map和join方法实现渲染页面的一个思路了。
在这里插入图片描述

<!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>数组map方法和join方法</title>
</head><body><script>const arr = ['red', 'blue', 'pink']// 1.数组map方法  处理数据并且返回一个数组// 不要用map方法来遍历数组,不然就违背了我们设计map方法的初衷了。map方法设计的主要原则是我想要得到一个数组返回一个数组,就用map。在进行map遍历的时候,可以让它处理一些数据,然后再把处理的结果返回给我,这才是map的正确处理方法。const newArr = arr.map(function (ele, index) {// console.log(ele)   // 数组元素// console.log(index)  // 索引号return ele + '颜色'})console.log(newArr)// 2. 数组join方法 把数组转换为字符串// 小括号为空则默认逗号分隔,因为我们都知道数组默认逗号分隔console.log(newArr.join())   // red颜色,blue颜色,pink颜色// 小括号是空字符串,则元素之间没有分隔符console.log(newArr.join(''))  // red颜色blue颜色pink颜色console.log(newArr.join('|'))  // red颜色|blue颜色|pink颜色</script>
</body></html>

步骤:
因为我们要做渲染,所以我们还是封装成一个渲染函数叫做render,因为我们后面不管是增加也好还是删除也好需要重新渲染页面,所以我们封装成一个函数。
把字符串赋值给tbody之后,tbody就可以把tr显示出来了。
在这里插入图片描述在这里插入图片描述
前面已经把数据存到本地存储里面,本地存储有数据,有数据我们就可以通过map的方法来遍历arr数组,在遍历的同时就可以return返回tr,返回字符串,在返回的同时把里面的相关数据换成了活的数据,map最大的特点是返回的是一个数组,那么就把return后面的东西返回给了数组装起来了,简单的来说我们有一个数组,return就把tr拿过来放到数组里面,这样我们就可以拿到数组了,经过刚才的验证我们发现数组里面确实存的是一个tr的字符串。
先把render函数封装一下,然后通过map方法拿到返回值的数组,接下来只需要把数组转换成字符串就可以追加给tbody了。在上面先把tbody获取一下。
共有数据几条:是根据数组的长度得来的,数组里面有几条数据就变成几,所以我们只需要把盒子拿过来,把它的值改成数组的长度就行了。在这里插入图片描述
在这里插入图片描述在这里插入图片描述
点击添加没有实现跳转,说明阻止默认行为成功了,接下来做非空判断,如果前3个为空就不允许增加数据。终止程序,并且返回一个提示框。首先把相关的数据获取过来,在提交事件里面。
当我们新增一条数据的时候一定要把它存储到本地存储里面,不然页面一刷新数据就丢失了。当它存储完毕之后,就可以拿到本地存储的最新数据,再去渲染我们的页面,这样页面就会多一条数据,又因为本地存储的数据不会丢失,所以再刷新,页面中的数据就不会消失了 。
在这里插入图片描述
页面一刷新,代码从上往下去执行,我们的初始值已经没有用到了,刚开始的本地存储一定要注释起来,要不然我们刚才录入的数据就会被覆盖掉了,页面就只剩初始的那一条数据了。这句话只是为了测试用的。(localStorage.setItem(‘data’, JSON.stringify(initData)))
在这里插入图片描述
这句话一读到的时候,我就要去本地存储里面读最新的data数据,我们前面已经把那两条数据存到data里面去了,那arr取过来的就是最新的那两条数据,有数据,所以后面的空数组不执行。然后代码从上往下继续,渲染函数刚开始不执行,但是下面有一个渲染函数,所以就回头调用,一回头调用我们就拿arr里面的两条数据来做渲染,所以只要往本地存储里面去存储了,那本地存储里面存的就是最新的数据,然后每次刷新页面,我就要从本地存储里面取最新的数据然后赋值给arr,那arr就可以来进行遍历渲染了,这就是它的执行过程,所以我们在做提交事件的时候,千万不要忘了最后一条:把最新的arr存到data里面,新增业务完成。

删除业务
为什么给tbody注册点击事件呢?因为我们会有新的数据产生,如果直接给按钮注册点击事件,我们用原先传统的方式是注册不上的,而 事件委托可以给新增的这些数据添加点击事件,又因为按钮有行都会变化的,而tbody是不变的,所以我们给他们的父亲tbody注册点击事件。这么多按钮,如何知道点了哪一条数据呢?知道当前按钮的索引号就可以了。map里面除了有一个ele参数以外,还有一个index可以得到数组元素的索引号,所以在遍历的时候就可以得到每一条数据的索引号了,现在只需给a加上一个自定义属性就可以了
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
没有数据arr.length就是0,0当假来看,则执行表达式2的那一个值,如果里面有2条数据,数字型的2当真看,则执行表达式1的结果,把结果返回过来再赋值给stuId。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>学生就业统计表</title><link rel="stylesheet" href="./iconfont/iconfont.css"><link rel="stylesheet" href="css/index.css" />
</head><body><h1>学生就业统计表</h1><form class="info" autocomplete="off"><input type="text" class="uname" name="uname" placeholder="姓名" /><input type="text" class="age" name="age" placeholder="年龄" /><input type="text" class="salary" name="salary" placeholder="薪资" /><select name="gender" class="gender"><option value=""></option><option value=""></option></select><select name="city" class="city"><option value="北京">北京</option><option value="上海">上海</option><option value="广州">广州</option><option value="深圳">深圳</option><option value="曹县">曹县</option></select><button class="add"><i class="iconfont icon-tianjia"></i>添加</button></form><div class="title">共有数据<span>0</span></div><table><thead><tr><th>ID</th><th>姓名</th><th>年龄</th><th>性别</th><th>薪资</th><th>就业城市</th><th>录入时间</th><th>操作</th></tr></thead><tbody><!-- <tr><td>1</td><td>迪丽热巴</td><td>23</td><td>女</td><td>12000</td><td>北京</td><td>2099/9/9 08:08:08</td><td><a href="javascript:"><i class="iconfont icon-shanchu"></i>删除</a></td></tr> --></tbody></table><script>// 参考数据const initData = [{stuId: 1,uname: '迪丽热巴',age: 22,salary: '12000',gender: '女',city: '北京',time: '2099/9/9 08:08:08'}]// 这里是为了测试,先存了一下,我们看到我们正确的拿到了数据,但是建议把这一行一定要把它注释起来,因为我们页面第一次打开肯定是没有数据的,所以我们拿个空数组去代替是没有问题的,后面做增加等业务的时候就可以把最新的数据放到本地存储里面,这样再打开页面的时候就可以从本地存储里面取真正的数据了。// 页面一打开从上往下依次去执行,这里有一个对象数组,下面一句话把这个数据存到本地存储里面,那就意味着我们每次打开页面都会重新存储一下这个data数据,把它存储到本地存储里面去,如果后面的数据发生了变化,我们一打开就又给我们覆盖掉了,所以一定要把下面这句话注释起来,因为本地存储已经存到浏览器里面去了,本地存储(aplication)一直都是存在的,所以我们没有必要打开页面又重新去填写了// localStorage.setItem('data', JSON.stringify(initData))   // 把这个解开之后就可以往本地存储里面去存这个数组了,本地存储有了数据我们就可以来遍历这条数据了// 1. 渲染业务// 1.1 先读取本地存储的数据// (1). 本地存储有数据则记得转换为对象然后存储到变量里面,后期用于渲染页面// 我们数组本质上也属于对象// (2). 如果没有数据,则用 空数组来代替 const arr = JSON.parse(localStorage.getItem('data')) || []console.log(arr)// 1.2 利用map和join方法来渲染页面const tbody = document.querySelector('tbody')// 渲染页面需要封装一个函数function render() {// (1). 利用map遍历数组,返回对应tr的数组// 每循环一次就返回一个tr,在返回的同时把相关的数据填充进去// map里面的第一个参数是ele(数组元素),  里面的每一条数组元素,也就是数组对象// map在遍历数组,结果发现只有一条数据它就会这么做,map一旦遍历就会有一个空数组等着map的返回值,一运行的时候就发现有一个return,把tr返回,在把tr返回的同时把里面的数据更换,所以旧表整个tr装到了数组里面,因为只有一条数据,所以只遍历一次就结束了,那我们就可以得到一个新的数组,那我们就可以把这个数组拿到了// map的另一个参数:index,可以得到数组元素的索引号,所以我在遍历的时候就可以拿到每一条数据的索引号了,现在只需要给a加一个自定义属性,data-id = 索引号const trArr = arr.map(function (ele, index) {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)// (2). 把数组转换为字符串 (join)// (3). 把生成的字符串换追加给tbody// 把多个tr转换成一个字符串tbody.innerHTML = trArr.join('')// 显示共有几条数据document.querySelector('.title span').innerHTML = arr.length}// 在打印的时候千万别忘了调用一下render函数render()// 到浏览器里面看看能不能拿到数组里面存着的tr,发现输出的是两个空数组,可能有一个情况是本地存储里面没有拿到数据,我没有遍历到,所以没有办法 往里面去存数据。到应用里面看看,果然本地存储里面没有数据,因为得到的是一个空数组,所以当然本地存储里面存不进去了,空数组没有办法遍历,所以没有办法加tr// 2. 新增业务// 2.1 form表单注册提交事件,阻止默认行为const info = document.querySelector('.info')const uname = document.querySelector('.uname')const age = document.querySelector('.age')const salary = document.querySelector('.salary')const gender = document.querySelector('.gender')const city = document.querySelector('.city')info.addEventListener('submit', function (e) {// 因为要阻止默认行为(跳转之类的),我们先不让它提交,所以要写个事件对象,然后去调用事件对象里面的方法e.preventDefault()// 2.2 非空判断if (!uname.value || !age.value || !salary.value) {return alert('输入内容不能为空')}// 2.3 给 arr 数组追加对象,里面存储表单获取过来的数据arr.push({// 新增一条新的数据,所以ID号就是原来的数组的长度+1,因为push是后追加// 这种做法不可取,因为如删除第一条数据之后再录入会出现ID号相同的情况// stuId: arr.length + 1,// 处理 stuId: 数组最后一条数据的stuId + 1// 还需考虑数据全部删除的情况// 全部删除之后再添加数据就报错了,因为我们数组里面没有数据,我们再用最后一条数据获取它的stuId就报错了,所以我们要加一个判断条件,如果没有数据,就直接让它赋值为1就行了 arr.length判断数组有没有长度stuId: arr.length ? arr[arr.length - 1].stuId + 1 : 1,uname: uname.value,age: age.value,salary: salary.value,gender: gender.value,city: city.value,// 用户录入了一条信息,它就自动获取当前的时间time: new Date().toLocaleString()})// 2.4 渲染页面和重置表单  (reset() 方法)render()// form表单是info,其实就是我们的this,因为this指向我们函数的调用者,也就是info。写this和info都可以this.reset()  // 重置表单(把表单输入框里面的值自动重置,恢复到原来的样子,清空内容)// 2.5 把数组重新存入本地存储里面,记得转换为JSON字符串存储// 因为我们已经有data这个数据了,一旦存了新的就把以前的覆盖掉了,实现了替换,这样就保证了data里面存的是最新的数据localStorage.setItem('data', JSON.stringify(arr))})// 3. 删除业务// 3.1 采用事件委托形式,给tbody注册点击事件tbody.addEventListener('click', function (e) {// 判断是否点击的是删除按钮  A链接if (e.target.tagName === 'A') {// alert(11)// 3.2 得到当前点击链接的索引号,渲染数据的时候,动态给a链接添加自定义属性例如 data-id="0"// 点击的那个对象有一个自定义属性叫data-id,这样可以拿到当前的索引号console.log(e.target.dataset.id)// 确认框确认是否要真的删除// confirm会返回两个值,如果点击确定就返回true,true就表示我要执行里面的代码,不用做删除,如果用户点击的是取消就返回false,就不执行大括号里面的代码if (confirm('你确定要删除这条数据吗?')) {// 3.3 根据索引号,利用 splice 删除数组这条数据arr.splice(e.target.dataset.id, 1)// 3.4 重新渲染页面render()// 3.5 把最新 arr 数组存入本地存储// 不然删了之后本地存储里面也还是有数据localStorage.setItem('data', JSON.stringify(arr))}}})</script>
</body></html>

下面这个案例未找到

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

相关文章:

WEB APIs day5

一、window对象 BOM属于window对象 1.BOM&#xff08;浏览器对象模型&#xff09; bom里面包含着dom,只不过bom我们平时用得比较少&#xff0c;我们经常使用的是dom操作&#xff0c;因为我们页面中的这些标签都是在dom中取的&#xff0c;所以我们操作dom多一点。 window对象…...

html动态爱心代码【一】(附源码)

前言 七夕马上就要到了&#xff0c;为了帮助大家高效表白&#xff0c;下面再给大家带来了实用的HTML浪漫表白代码(附源码)背景音乐&#xff0c;可用于520&#xff0c;情人节&#xff0c;生日&#xff0c;表白等场景&#xff0c;可直接使用。 效果演示 文案修改 var loverNam…...

【仿写tomcat】六、解析xml文件配置端口、线程池核心参数

线程池改造 上一篇文章中我们用了Excutors创建了线程&#xff0c;这里我们将它改造成包含所有线程池核心参数的形式。 package com.tomcatServer.http;import java.util.concurrent.*;/*** 线程池跑龙套** author ez4sterben* date 2023/08/05*/ public class ThreadPool {pr…...

Android Studio 接入OpenCV最简单的例子 : 实现灰度图效果

1. 前言 上文 我们在Windows电脑上实现了人脸功能&#xff0c;接下来我们要把人脸识别的功能移植到Android上。 那么首先第一步&#xff0c;就是要创建一个Native的Android项目&#xff0c;并且配置好OpenGL&#xff0c;并能够调用成功。 这里我们使用的是openCV-4.8.0&#x…...

(1)、扩展SpringCache一站式解决缓存击穿,穿透,雪崩

1、问题描述 我们在使用SpringCache的@Cacheable注解时,发现并没有设置过期时间这个功能。 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @I...

Rancher使用cert-manager安装报错解决

报错&#xff1a; rancher-rke-01:~/rke/rancher-helm/rancher # helm install rancher rancher-stable/rancher --namespace cattle-system --set hostnamewww.rancher.local Error: INSTALLATION FAILED: Internal error occurred: failed calling webhook "webhook…...

Harvard transformer NLP 模型 openNMT 简介入门

项目网址&#xff1a; OpenNMT - Open-Source Neural Machine Translation logo&#xff1a; 一&#xff0c;从应用的层面先跑通 Harvard transformer GitHub - harvardnlp/annotated-transformer: An annotated implementation of the Transformer paper. ​git clone https…...

【数据结构OJ题】用栈实现队列

原题链接&#xff1a;https://leetcode.cn/problems/implement-queue-using-stacks/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 用两个栈实现&#xff0c;一个栈进行入队操作&#xff0c;另一个栈进行出队操作。 出队操作&#xff1a; 当出队的栈…...

通达信指标公式15:除权除息数据统计分析

#1.关于除权除息指标的介绍&#xff1a;本指标是小红牛原创指标之一&#xff0c;觉得有必要研究一下这个问题&#xff0c;所以就花时间整理一下这个指标相关内容&#xff0c;大家可以在本源码基础上&#xff0c;进一步优化自己的思路。本指标为通达信幅图指标&#xff0c;可以做…...

day-27 代码随想录算法训练营(19)回溯part03

39.组合总和 分析&#xff1a;同一个数可以选多次&#xff0c;但是不能有重复的答案&#xff1b; 思路&#xff1a;横向遍历&#xff0c;纵向递归&#xff08;不同的是递归的时候不需要跳到下一个位置&#xff0c;因为同一个数可以选多次&#xff09; class Solution { publ…...

CSDN编程题-每日一练(2023-08-22)

CSDN编程题-每日一练(2023-08-22) 一、题目名称:最长递增区间二、题目名称:K树三、题目名称:小Q的价值无向图一、题目名称:最长递增区间 时间限制:1000ms内存限制:256M 题目描述: 给一个无序数组,求最长递增的区间长度。如:[5,2,3,8,1,9] 最长区间 2,3,8 长度为 3。…...

使用 KubeBlocks 为 K8s 提供稳如老狗的数据库服务

原文链接&#xff1a;https://forum.laf.run/d/994 大家好&#xff01;今天这篇文章主要向大家介绍 Sealos 的数据库服务。在 Sealos 上数据库后端服务由 KubeBlocks 提供&#xff0c;为用户的数据库应用保驾护航。无论你是在公有云还是本地环境中使用&#xff0c;Sealos 都能为…...

SFL212B-10-21-15、SFL212B-20-21-40喷嘴挡板伺服阀

SFL212B-05-21-10、SFL212B-10-21-15、SFL212B-20-21-40、SFL212-05-32-10、SFL212-10-32-15、SFL212-20-32-40、SFL212A-05-21-10、SFL212A-10-21-15、SFL212A-20-21-40喷嘴挡板力反馈伺服阀&#xff0c;外置伺服放大器&#xff0c;四通&#xff0c;带阀芯阀套的两级伺服阀&am…...

阿里云100元预算可选的云服务器配置2核2G3M带宽

阿里云服务器100元可以买到哪些配置&#xff1f;如果是一年时长&#xff0c;轻量应用服务器2核2G3M带宽一年108元&#xff0c;系统盘为50GB高效云盘。以前阿里云服务器ECS卖过35元一年、69元、88元、89元和99元的都有过&#xff0c;但是现在整体费用上涨&#xff0c;入门级云服…...

Linux问题--docker启动mysql时提示3306端口被占用

问题描述&#xff1a; 解决方法&#xff1a; 1.如果需要kill掉mysqld服务可以先通过 lsof -i :3306 2. 查询到占用3306的PID&#xff0c;随后使用 kill -15 PID 来kill掉mysqld服务。 最后结果...

2023年中秋月饼市场趋势分析(月饼京东销售数据分析)

中秋将至&#xff0c;月饼作为节令食品将再次掀起消费热潮。今年月饼市场的需求如何呢&#xff0c;是更受欢迎还是热度有所降低&#xff0c;结合数据我们一起来看今年月饼市场的销售表现。 在这里&#xff0c;我们分别选取了2022年第31周-32周和2023年第31周-32周&#xff08;…...

A Survey on Model Compression for Large Language Models

本文是LLM系列文章&#xff0c;关于模型压缩相关综述&#xff0c;针对《A Survey on Model Compression for Large Language Models》的翻译。 大模型的模型压缩综述 摘要1 引言2 方法3 度量和基准3.1 度量3.2 基准 4 挑战和未来方向5 结论 摘要 大型语言模型&#xff08;LLM…...

读取/加载 properties/yml 配置文件

大家好 , 我是苏麟 , 今天带来一个简单好用的东西 . 读取/加载 properties/yml配置文件 基于PropertiesConfiguration读取配置文件 引入依赖 <!--加载yml资源--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-b…...

UG\NX二次开发 创建中心线

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,C\C++,Qt-CSDN博客 简介: 下面是在制图模块创建中心线的例子,用的是ufun函数。 效果: 代码: #include "me.hpp"#include <stdio.h> #include <string.h> #include <uf.h>…...

用java语言写一个网页爬虫 用于获取图片

以下是一个简单的Java程序&#xff0c;用于爬取网站上的图片并下载到本地文件夹&#xff1a; import java.io.*; import java.net.*;public class ImageSpider {public static void main(String[] args) {// 确定要爬取的网站URL和本地保存目录String url "https://www.…...

三数之和-LeetCode

给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 示例 1&a…...

ubuntu 对多CPU统一设置高性能模式

一、问题描述 之前在网上找到的CPU设置高性能模式&#xff0c;只能设置CPU0单个CPU&#xff0c;下述是对多核CPU统一设置工作模式。 二、软件安装与设置 执行下述命令sudo apt-get install indicator-cpufreq,然后重启电脑。此时&#xff0c;界面右上角会出现如下图标&#xf…...

志凌海纳 SmartX 携手灵雀云推出全栈云原生联合解决方案

近日&#xff0c;北京志凌海纳科技有限公司&#xff08;以下简称“SmartX”&#xff09;与北京凌云雀科技有限公司&#xff08;以下简称“灵雀云”&#xff09;联合推出全栈云原生联合解决方案&#xff0c;为客户提供从基础设施到容器云平台的一站式服务&#xff0c;加速客户云…...

排名前 6 位的数学编程语言

0 说明 任何对数学感兴趣或计划学习数学的人&#xff0c;都应该至少对编程语言有一定的流利程度。您不仅会更有就业能力&#xff0c;还可以更深入地理解和探索数学。那么你应该学习什么语言呢&#xff1f; 1.python 对于任何正在学习数学的人来说&#xff0c;Python都是一门很棒…...

arm:day6

实现UART通信&#xff1a; 1.键盘输入一个字符a,串口工具显示b 2.键盘输入一个字符串"nihao",串口工具显示"nihao" uart.h #ifndef __UART4_H__ #define __UART4_H__#include "stm32mp1xx_uart.h" #include "stm32mp1xx_gpio.h" #in…...

MyBatis快速入门以及环境搭建和CRUD的实现

目录 前言 一、MyBatis简介 1.MyBatis是什么 2.MyBatis的特点 3.mybatis的作用 4.MyBatis的应用场景 5.MyBatis优缺点 二、相关概念 1.ORM概述 2.常见的ORM框架 3.什么是持久层框架 三、MyBatis的工作原理 1.框架交互 2.工作原理 ​编辑 四、MyBatis环境搭建 1…...

基于Pytorch实现的声纹识别系统

前言 本项目使用了EcapaTdnn、ResNetSE、ERes2Net、CAM等多种先进的声纹识别模型&#xff0c;不排除以后会支持更多模型&#xff0c;同时本项目也支持了MelSpectrogram、Spectrogram、MFCC、Fbank等多种数据预处理方法&#xff0c;使用了ArcFace Loss&#xff0c;ArcFace loss…...

Fast DDS (2)

1、结构&#xff1a; Fast DDS的架构如下图所示&#xff0c;可以看到以下不同环境的层模型&#xff1a; 应用层&#xff1a;利用Fast DDS API 在分布式系统中实现通信的用户应用程序。Fast DDS层&#xff1a;DDS 通信中间件的稳健实现。它允许部署一个或多个 DDS 域&#xff…...

HarmonyOS/OpenHarmony应用开发-ArkTS语言渲染控制if/else条件渲染

ArkTS提供了渲染控制的能力。条件渲染可根据应用的不同状态&#xff0c;使用if、else和else if渲染对应状态下的UI内容。说明&#xff1a;从API version 9开始&#xff0c;该接口支持在ArkTS卡片中使用。一、使用规则 支持if、else和else if语句。 if、else if后跟随的条件语句…...

飞天使-k8s基础组件分析-pod

文章目录 pod介绍pod 生命周期init 容器容器handlerpod中容器共享进程空间sidecar 容器共享 参考链接 pod介绍 最小的容器单元 为啥需要pod? 答: 多个进程丢一个容器里&#xff0c;会因为容器里个别进程出问题而出现蝴蝶效应&#xff0c;pod 是更高级的处理方式pod 如何共享相…...

css题库

什么是css&#xff1f; CSS 是“Cascading Style Sheet”的缩写&#xff0c;中文意思为“层叠样式表”&#xff0c;它是一种标准的样式表语言&#xff0c;用于描述网页的表现形式&#xff08;例如网页元素的位置、大小、颜色等&#xff09;。 为什么最好把 CSS 的 link 标签放在…...

中文医疗大模型汇总

【写在前面】随着大语言模型的发展&#xff0c;越来越多的垂直领域的LLM发不出来&#xff0c;针对医学这一垂直领域的LLM进行整理&#xff0c;放在这里&#xff0c;希望对大家有一定的帮助吧。还会继续更新&#xff0c;大家有兴趣的话可以持续关注。 更多关于中文医疗自然语言处…...

smiley-http-proxy-servlet 实现springboot 接口反向代理,站点代理,项目鉴权,安全的引入第三方项目服务

背景&#xff1a; 项目初期 和硬件集成&#xff0c;实现了些功能服务&#xff0c;由于是局域网环境&#xff0c;安全问题当时都可以最小化无视。随着对接的服务越来越多&#xff0c;部分功能上云&#xff0c;此时就需要有一种手段可以控制到其他项目/接口的访问权限。 无疑 反向…...

Java集合利器 Map Set

Map & Set 一、概念二、Map三、Set下期预告 一、概念 Map和Set是一种专门用来进行搜索的数据结构&#xff0c;其搜索的效率与其具体的实例化子类有关。它们分别定义了两种不同的数据结构和特点&#xff1a; Map&#xff08;映射&#xff09; &#xff1a;Map是一种键值对&…...

HJ106 字符逆序

描述 将一个字符串str的内容颠倒过来&#xff0c;并输出。 数据范围&#xff1a;1≤len(str)≤10000 1≤len(str)≤10000 输入描述&#xff1a; 输入一个字符串&#xff0c;可以有空格 输出描述&#xff1a; 输出逆序的字符串 示例1 输入&#xff1a; I am a student 输…...

sentinel的基本使用

在一些互联网项目中高并发的场景很多&#xff0c;瞬间流量很大&#xff0c;会导致我们服务不可用。 sentinel则可以保证我们服务的正常运行&#xff0c;提供限流、熔断、降级等方法来实现 一.限流&#xff1a; 1.导入坐标 <dependency><groupId>com.alibaba.c…...

【STM32】串口通信乱码(认识系统时钟来源)

使用 stm32f407 与电脑主机进行串口通信时&#xff0c;串口助手打印乱码&#xff0c;主要从以下方面进行排查&#xff1a; 检查传输协议设置是否一致&#xff08;波特率、数据位、停止位、校验位&#xff09;检查MCU外部晶振频率是否和库函数设置的一致 最终发现是外部晶振频…...

Java实现敏感词过滤功能

敏感词过滤功能实现 1.GitHub上下载敏感词文件 2.将敏感词文件放在resources目录下 在业务中可以将文本中的敏感词写入数据库便于管理。 3.提供实现类demo 代码编写思路如下&#xff1a;1.将敏感词加载到list中&#xff0c;2.添加到StringSearch中&#xff0c;3.校验&#x…...

大数据向量检索的细节问题

背景:现有亿级别数据(条数),其文本大小约为150G,label为字符串,content为文本。用于向量检索,采用上次的试验进行,但有如下问题需要面对: 1、向量维度及所需空间 向量维度一版采用768的bert系列的模型推理得到,openai也有类似的功能,不过是2倍的维度(即1536),至…...

如何让智能搜索引擎更灵活、更高效?

随着互联网的发展和普及&#xff0c;搜索引擎已经成为人们获取信息、解决问题的主要工具之一。 然而&#xff0c;传统的搜索引擎在面对大数据时&#xff0c;往往存在着搜索效率低下、搜索结果精准度不够等问题。 为了解决这些问题&#xff0c;越来越多的企业开始采用智能搜索技…...

C++set集合与并查集map映射,哈希表应用实例B3632 集合运算 1P1918 保龄球

集合的性质 无序性互异性确定性 B3632 集合运算 1 题面 题目背景 集合是数学中的一个概念&#xff0c;用通俗的话来讲就是&#xff1a;一大堆数在一起就构成了集合。 集合有如下的特性&#xff1a; 无序性&#xff1a;任一个集合中&#xff0c;每个元素的地位都是相同的&…...

easyexcel合并单元格底色

一、效果图 二、导出接口代码 PostMapping("selectAllMagicExport")public void selectAllMagicExport(HttpServletRequest request, HttpServletResponse response) throws IOException {ServiceResult<SearchResult<TestMetLineFe2o3Export>> result …...

OpenCV图片校正

OpenCV图片校正 背景几种校正方法1.傅里叶变换 霍夫变换 直线 角度 旋转3.四点透视 角度 旋转4.检测矩形轮廓 角度 旋转参考 背景 遇到偏的图片想要校正成水平或者垂直的。 几种校正方法 对于倾斜的图片通过矫正可以得到水平的图片。一般有如下几种基于opencv的组合方…...

数字孪生流域共建共享相关政策解读

当前数字孪生技术在水利方面的应用刚起步&#xff0c;2021年水利部首次提出“数字孪生流域”概念&#xff0c;即以物理流域为单元、时空数据为底座、数学模型为核心、水利知识为驱动&#xff0c;对物理流域全要素和水利治理管理活动全过程的数字映射、智能模拟、前瞻预演&#…...

FSC147数据集格式解析

一. 引言 在研究很多深度学习框架的时候&#xff0c;往往需要使用到FSC147格式数据集&#xff0c;若要是想在自己的数据集上验证深度学习框架&#xff0c;就需要自己制作数据集以及相关标签&#xff0c;在论文Learning To Count Everything中&#xff0c;该数据集首次被提出。 …...

el-element中el-tabs案例的使用

el-element中el-tabs的使用 代码呈现 <template><div class"enterprise-audit"><div class"card"><div class"cardTitle"><p>交易查询</p></div><el-tabs v-model"activeName" tab-cl…...

tomcat结构目录有哪些?

bin 启动&#xff0c;关闭和其他脚本。这些 .sh文件&#xff08;对于Unix系统&#xff09;是这些.bat文件的功能副本&#xff08;对于 Windows系统&#xff09;。由于Win32命令行缺少某些功能&#xff0c;因此此处包含一些其他文件。 比如说&#xff1a;windows下启动tomcat用的…...

生成式AI系列 —— DCGAN生成手写数字

1、模型构建 1.1 构建生成器 # 导入软件包 import torch import torch.nn as nnclass Generator(nn.Module):def __init__(self, z_dim20, image_size256):super(Generator, self).__init__()self.layer1 nn.Sequential(nn.ConvTranspose2d(z_dim, image_size * 32,kernel_s…...

vscode-vue项目格式化+语法检验-草稿

Vue学习笔记7 - 在Vscode中配置Vetur&#xff0c;ESlint&#xff0c;Prettier_vetur规则_Myron.Maoyz的博客-CSDN博客...

【Java从0到1学习】10 Java常用类汇总

1. System类 System类对读者来说并不陌生&#xff0c;因为在之前所学知识中&#xff0c;需要打印结果时&#xff0c;使用的都是“System.out.println();”语句&#xff0c;这句代码中就使用了System类。System类定义了一些与系统相关的属性和方法&#xff0c;它所提供的属性和…...