API学习01
三种变量声明
变量声明有三个var、let、const
-
var:已经被淘汰
-
let:可以对已声明的变量进行修改,但不允许重复声明,循环中常用
-
const:声明常量,基础数据类型的变量一旦被赋值就不能修改,也不允许重复声明。但如果修改的是由const定义的引用类型(例如对象),可以修改对象里面的内容
在 let 和 const中优先 const ,建议定义变量时用 const 定义。之后若进行修改再改为 let
[一篇三种变量的比较的博客](搞懂JavaScript中var和let、const的区别与使用_var let const 区别和用法-CSDN博客)
const arr = ['red', 'yellow', 'green']
arr.push('blue')
// const 声明的数组内容可以改变,数组的地址没有变,还是那个数组
console.log(arr)
// 下面这种操作是错误的,因为会开辟新的堆空间,数组的地址发生了变化
// arr = ['red', 'yellow', 'green', 'blue']
同样对象也可以修改内容
const obj = {
name: '小明',
age: 18,
}
obj.home = '山东'
console.log(obj)
Web API 基本认知
作用与分类
-
作用:使用 JS 去操作 html 和浏览器
-
分类:DOM(文档对象类型)、BOM(浏览器对象类型)
什么是DOM
-
DOM(Document Object Model——文档对象模型)是用来呈现以及与任意 HTML 或 XML文档交互的API
即:DOM是浏览器提供的一套专门用来 操作网页内容 的功能
-
DOM作用:开发网页内容特效和实现用户交互
DOM树
将 HTML 文档以树状结构直观的表现出来,我们称之为文档树或 DOM 树
描述网页内容关系的名词
作用:文档树直观的体现了标签与标签之间的关系
DOM对象
- DOM对象:浏览器根据 html 标签生成的 JS 对象
所有标签的属性都可以在这个对象上找到,修改这个对象的属性会自动映射到标签身上。所有标签都是DOM对象
-
DOM核心思想:把网页内容当成对象来处理
-
document 对象:是DOM里提供的一个对象,它提供的属性和方法都是用来访问和操作网页内容的,网页的所有内容都在document里面
整个页面就是document对象
获取DOM元素
- 根据css选择器来获取DOM元素(重点)
- 其他获取DOM元素方法(了解)
css选择器获取
-
选择匹配的第一个元素
语法:document.querySelector(‘css选择器’)
返回值:CSS选择器匹配的第一个元素,一个 HTMLElement对象。 如果没有匹配到,则返回null。
-
选择匹配的所有元素
语法:document.querySelectorAll(‘css选择器’)
返回值:CSS选择器匹配的NodeList 对象集合
得到的是一个伪数组:
有长度有索引号的数组,但是没有 pop() push() 等数组方法。想要得到里面的每一个对象,则需要遍历(for)的方式获得。
哪怕只有一个元素,通过querySelectAll() 获取过来的也是一个伪数组,里面只有一个元素而已
<body>
<div class="box">123</div>
<div class="box">abc</div>
<p id="nav">导航栏</p>
<ul>
<li>测试1</li>
<li>测试2</li>
<li>测试3</li>
</ul>
<script>
// 获取匹配的第一个元素
// 1. 通过标签
const box = document.querySelector('div')
// 2. 通过类选择器
const box1 = document.querySelector('.box')
console.log(box === box1) // true
// 3. 通过id选择器
const nav = document.querySelector('#nav')
console.log(nav)
// 获取第一个li
const li = document.querySelector('ul li:first-child')
console.log(li)
// 选择匹配的所有元素
const liAll = document.querySelectorAll('ul li')
console.log(liAll)
</script>
</body>
页面输出
其他获取
已经不再常用
// document.getElementById() 根据Id获取一个元素
const nav = document.getElementById('nav')
console.log(nav)
// document.getElementsByTagName() 通过标签获取匹配的所有元素
const p = document.getElementsByTagName('p')
console.log(p)
// document.getElementsByClassName() 通过类名获取匹配的所有元素
const box = document.getElementsByClassName('box')
console.log(box)
通过标签和类名获取时是elements,而通过id获取是element,以为id是唯一的
这种方式下的传递的参数无论是类名还是id名和传递标签参数写法类似,并不会有类的 “.” 和 id 的 “#”,第一种方式获取DOM元素更推荐
操作DOM元素
操作元素内容
- DOM对象都是根据标签生成的,所有操作标签,本质上就是操作DOM对象。
- 就是通过点语法操作DOM对象
操作标签元素里面内容的方式:
- 对象.innerText
- 对象.innerHTML
两者的区别就是innerText属性不识别标签,innerHTML属性识别标签,所有建议使用innerHTML
<body>
<div class="box">我是文件内容</div>
<div class="box1">我是文件内容</div>
<script>
// 1. 获取元素
const box = document.querySelector('.box')
// 修改文字内容 对象.innerText属性
// 直接使用相当于获取元素内容
console.log(box.innerText)
// box.innerText = '已修改'
box.innerText = ('<strong>不识别标签</strong>')
const box1 = document.querySelector('.box1')
box1.innerHTML = ('<strong>识别标签</strong>')
</script>
</body>
页面输出
年会抽奖案例
需求:从数组随机抽取一等奖、二等奖和三等奖,显示到对应的标签里面。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.wrapper {
width: 840px;
height: 420px;
padding: 100px 250px;
box-sizing: border-box;
}
</style>
</head>
<body>
<div class="wrapper">
<strong>年会抽奖</strong>
<h1>一等奖:<span id="one">***</span></h1>
<h3>二等奖:<span id="two">**</span></h3>
<h5>三等奖:<span id="three">小兰</span></h5>
</div>
<script>
// 1. 声明数组
const arr = ['小红', '小明', '小兰', '小华', '小强', '小丽', '小雨']
// 随机生成数字
function getRandom() {
return Math.floor(Math.random() * arr.length)
}
// 2. 获取要修改的标签
const span = document.querySelectorAll('span')
// 3. 遍历修改
for (const spanKey in span) {
// 获取随机数
const num = getRandom()
// 找到随机数对应的数字元素,装入span
span[spanKey].innerHTML = `${arr[num]}`
// 删除已获奖的
arr.splice(num, 1)
}
</script>
</body>
</html>
页面输出
修改元素属性
1. 操作元素常用属性
通过JS设置标签元素属性,例如href、title、scr等
语法:对象.属性 = 值
随机显示图片
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>随机显示图片</title>
<style>
img {
width: 400px;
height: 380px;
}
</style>
</head>
<body>
<img alt="" src="../img/1.webp">
<script>
function getRandom(N, M) {
return Math.floor((Math.random() * (M - N + 1) + N))
}
// 1. 获取元素
const img = document.querySelector('img')
random = getRandom(1, 6)
img.src = `../img/${random}.webp`
</script>
</body>
</html>
2.操作元素样式属性
通过style属性操作css
生成的是行内样式 权重高
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box {
width: 400px;
height: 400px;
background-color: #b3d4fc;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
// 1. 获取元素
const box = document.querySelector('.box')
// 要写单位
box.style.width = '600px'
// background-color 这种有连接符的可以采用小驼峰
box.style.backgroundColor = '#abcd99'
// 添加边框属性
box.style.border = '5px solid red'
</script>
</body>
更换背景图片
需求:当我们刷新页面,页面中的背景图片随机显示不同的图片
css页面背景图片 background-image
标签选择body:可以直接写 document.body.style
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body {
background: url("../img/bg1.jpg") no-repeat top center/cover;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
// 数组存放图片路径
const bg = ['../img/bg1.jpg', '../img/bg2.jpg', '../img/bg3.jpg', '../img/bg4.jpg', '../img/bg5.jpg']
// 获取随机数
const random = Math.floor(Math.random() * bg.length)
// 修改body背景
document.body.style.backgroundImage = `url(${bg[random]})`
</script>
</body>
</html>
效果预览
通过类名操作css
-
大规模改变样式使用
语法:元素.className = ‘类名’
由于class是关键字,所以使用className去代替
className是使用新值换旧值,会直接覆盖之前的类只保留新类,若想保留之前的类名下的属性则使用元素.className = ‘旧类名 新类名’,值得注意的是重复的属性新类名会覆盖旧类名,旧类名中不重复的属性会保留
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box {
width: 200px;
height: 200px;
background-color: #b3d4fc;
border: 3px solid red;
}
.box1 {
width: 500px;
height: 500px;
background-color: pink;
/*border: 3px solid red;*/
}
</style>
</head>
<body>
<div class="box1"></div>
<script>
const div = document.querySelector('div')
// 已经选择类名 不需要加 ”.“
div.className = 'box1 box'
</script>
</body>
</html>
通过classList操作类控制css
后两种都适合修改大量样式,这种方式更为推荐!!!这两种都不需要加“.”
可以解决className 容易覆盖以前的类名
语法:
追加一个类:元素.classList.add(‘类名’) // 相当于:元素.className = ‘旧类名 新类名’
删除一个类:元素.classList.remove(‘类名’)
切换一个类:元素.classList.toggle(‘类名’) //相当于:元素.className = ‘类名’
3.操作表单元素
- 表单很多情况,也需要修改属性,比如点击眼睛,可以让输入的密码显示出来,本质上是将表单类型转换为文本框
获取:DOM对象.属性名
设置:DOM对象.属性名 = 新值
-
表单属性中,有些一点击就会有效果,再点击就会移除效果,一律使用布尔值表示,如果为true代表添加了该属性,如果为false代表移除了该属性
比如:disabled、checked、selected
复选框:
<label>
<input checked="checked" type="checkbox">
</label>
<script>
// 1. 获取元素
const ipt = document.querySelector('input')
// 勾选是true 没勾选是false
console.log(ipt.checked) //true
// 通过checked = false 取消勾选
ipt.checked = false
</script>
</body>
按钮:
<body>
<label>
敲代码<input checked="checked" type="checkbox">
</label>
<button>点击</button>
<script>
// 1. 获取元素
const btn = document.querySelector('button')
// 默认false 即不禁用
console.log(btn.disabled) // false
// 2. 修改属性,禁用button
btn.disabled = true
</script>
</body>
4.自定义属性
-
标准属性:标签自带的属性,可以直接用对象的点语法操作
-
自定义属性:html5推出的,用data-xxx 来自定义一个属性,在标签上使用data-xxx定义
用DOM对象获取时采用:对象.dataset.xxx
<body>
<div data-id="1">1</div>
<div data-id="2">2</div>
<div data-id="3">3</div>
<div data-id="4">4</div>
<div data-id="5">5</div>
<script>
// 获取第一个div
const one = document.querySelector('div')
// 获取自定义属性
console.log(one.dataset)
// dataset是包括所有自定义属性的对象 获取对象的属性使用点语法
console.log(typeof one.dataset) // object
// 获取自定义的data-id属性
console.log(one.dataset.id) // 1
</script>
</body>
5.间歇函数
网页中经常会需要一种功能:每隔一段时间需要自动执行一段代码,不需要我们手动去触发
例如:网页中倒计时(红包雨将在60s后来临、距离促销活动开始还有xx时xx分xx秒…)
要实现这种需要就用到了定时器函数,这里先讲一下间歇函数
-
开启定时器:setInterval(函数,间隔时间)
每隔一段时间,执行一次函数,函数可以是匿名函数,间隔时间是毫秒单位
为防止每个定时器之间产生干扰,每个定时器的返回值是id号,用let接受,因为定时器的开关会影响id值
-
关闭定时器:
let 变量名 = setInterval(函数,间隔时间)
clearInterval(变量名)
<script>
// setInterval(函数,间隔时间)
// 使用匿名函数
setInterval(function () {
// 每隔一秒打印一次
console.log('Hi')
}, 1000)
// 不使用匿名函数时,参数不能写成fn(),或者参数加上引号写成'fn()',但是不推荐使用
// 每个定时器的返回值是一个id 区分不同定时器
let n = setInterval(fn, 1000)
console.log(n) // 2
// 关闭定时器 通常根据事情进行定时器的开关
clearInterval(n)
function fn() {
console.log('执行一次')
}
</script>
6.阅读注册协议案例
需求:按钮60秒之后才可以使用
分析:
① 开始先把按钮禁用(disabled 属性)
② 一定要获取元素
③ 函数内处理逻辑 秒数开始减减 按钮里面的文字跟着一起变化 如果秒数等于0 停止定时器
<body>
<label>
<textarea cols="50" rows="30">
用户注册协议
我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议我是协议
</textarea>
</label>
<br>
<button disabled>我已经阅读用户协议</button>
<script>
const btn = document.querySelector('button')
let t = 5
let n = setInterval(function () {
btn.innerHTML = `我已经阅读用户协议${t}s`
t--
if (t === 0) {
clearInterval(n)
btn.disabled = false
btn.innerHTML = '同意'
}
}, 1000)
</script>
</body>
效果演示
阅读协议
事件监听
介绍
事件是在编程时系统内发生的动作或者发生的事情,比如用户在网页上单击一个按钮
事件监听:让程序检查是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 绑定事件或者注册事件。比如鼠标经过显示下拉菜单、鼠标点击”<“ ”>“切换轮播图
最新语法
语法:元素对象.addEventListener(‘事件类型’,执行函数)
-
事件监听三要素:
事件源:哪个DOM元素触发了事件,需要获取的DOM元素
事件类型:用什么方式触发的,例如鼠标单击click、鼠标经过mouseover
事件调用函数:发生后要怎么做
<body>
<button>点击</button>
<script>
// 点击按钮弹出对话框
// 1. 事件源 button
// 2. 事件类型 鼠标点击
// 3. 事件处理程序
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
alert('你好呀~')
})
</script>
</body>
事件类型
事件对象
-
事件对象:这个对象里有事件触发时的相关信息,例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
-
使用场景:可以判断用户按下哪个键,比如按下回车键可以发布新闻 ,可以判断鼠标点击了哪个元素,从而做相应的操作
-
事件对象的获取:在事件绑定的回调函数的第一个参数就是事件对象,一般命名为event、ev、e
例如:元素.addEventListenner(‘click’,function(e){
})
事件对象的一些属性
环境对象
环境变量:指的是函数内部特殊的变量this,他代表着当前函数运行时所处的环境,弄清楚this的指向,可以让我们代码更简洁
1.函数的调用方式不同,this 指代的对象也不同
2.【谁调用, this 就是谁】 是判断 this 指向的粗略规则
3.直接调用函数,其实相当于是 window.函数,所以 this 指代 window
回调函数
如果函数A作为函数B的参数时,称函数A为回调函数,例如定时器函数setInterval中的执行函数,事件监听的执行函数。回调两字可以理解为刚开始不会立刻执行,需要满足一些条件后再执行
案例
点击关闭广告
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.ad {
position: relative;
width: 1000px;
height: 200px;
background-color: pink;
margin: 100px auto;
text-align: center;
font-size: 50px;
line-height: 200px;
font-weight: 700;
}
.close {
position: absolute;
right: 20px;
top: 10px;
width: 20px;
height: 20px;
background-color: skyblue;
text-align: center;
line-height: 20px;
font-size: 16px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="ad">
我是广告
<div class="close">X</div>
</div>
<script>
// 1. 获取事件源
const close = document.querySelector('.close')
// 关闭的大盒子
const ad = document.querySelector('.ad')
// 2. 事件监听
close.addEventListener('click', function () {
ad.style.display = 'none'
})
</script>
</body>
</html>
效果展示
广告关闭
随机问答案例
分析:
① 点击开始按钮随机抽取数组的一个数据,放到页面中
② 点击结束按钮删除数组当前抽取的一个数据
③ 当抽取到最后一个数据的时候,两个按钮同时禁用(写点开始里面,只剩最后一个数据不用抽了 )
核心:利用定时器快速展示,停止定时器结束展示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>随机点名</title>
<style>
h2 {
text-align: center;
}
.big {
width: 400px;
height: 200px;
margin: 0 auto;
border: #555555 solid 2px;
}
.box {
padding: 30px;
font-size: 20px;
}
.box span:nth-child(2) {
color: red;
font-weight: 700;
}
button {
padding: 6px 20px;
margin: 0 20px;
cursor: pointer;
}
.btn {
padding-top: 50px;
text-align: center;
}
</style>
</head>
<body>
<h2>随机点名</h2>
<div class="big">
<div class="box">
<span>名字是:</span>
<span>关羽</span>
</div>
<div class="btn">
<button class="start">开始</button>
<button class="end">结束</button>
</div>
<script>
// 数据数组
const nameList = ['马超', '黄忠', '赵云', '关羽', '张飞', '刘备', '小乔', '孙尚香', '诸葛亮', '孙策', '周瑜', '黄盖']
// 1. 获取事件源
const start = document.querySelector('.start')
// 2. 开始按钮点击事件
const name = document.querySelector('.box span:nth-child(2)')
console.log(name)
// 设置一个全局变量接受定时器Id
let timeId = 0
// 设置一个全局变量接受随机数
let random = 0
start.addEventListener('click', function () {
// 点击开始后 开始按钮禁用
start.disabled = true
timeId = setInterval(function () {
random = getRandom()
// console.log(random)
name.innerHTML = `${nameList[random]}`
}, 100)
// 当仅剩一个名字时, 不需要再抽取 禁用所有按钮
if (nameList.length === 1) {
end.disabled = true
}
})
// 3. 结束按钮点击按钮
const end = document.querySelector('.end')
end.addEventListener('click', function () {
// 点完一次 恢复开始按钮
start.disabled = false
// 关闭定时器
clearInterval(timeId)
// 删除已经抽到的名字
nameList.splice(random, 1)
console.log(nameList)
})
// 获取随机数
function getRandom() {
return Math.floor(Math.random() * nameList.length)
}
</script>
</div>
</body>
</html>
效果展示
随机点名
轮播图案例
需求:当点击左右的按钮,可以切换轮播图
分析:
①:右侧按钮点击,变量++,如果大于等于8,则复原0
②:左侧按钮点击,变量–,如果小于0,则复原最后一张
③:鼠标经过暂停定时器
④:鼠标离开开启定时器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>轮播图</title>
<style>
* {
box-sizing: border-box;
}
.slider {
width: 560px;
height: 400px;
overflow: hidden;
}
.slider-wrapper {
width: 100%;
height: 320px;
}
.slider-wrapper img {
width: 100%;
height: 100%;
display: block;
}
.slider-footer {
height: 80px;
background-color: rgb(100, 67, 68);
padding: 12px 12px 0 12px;
position: relative;
}
.slider-footer .toggle {
position: absolute;
right: 0;
top: 12px;
display: flex;
}
.slider-footer .toggle button {
margin-right: 12px;
width: 28px;
height: 28px;
appearance: none;
border: none;
background: rgba(255, 255, 255, 0.1);
color: #fff;
border-radius: 4px;
cursor: pointer;
}
.slider-footer .toggle button:hover {
background: rgba(255, 255, 255, 0.2);
}
.slider-footer p {
color: #fff;
font-size: 18px;
margin: 0 0 10px;
}
.slider-indicator {
margin: 0;
padding: 0;
list-style: none;
display: flex;
align-items: center;
}
.slider-indicator li {
width: 8px;
height: 8px;
margin: 4px;
border-radius: 50%;
background: #fff;
opacity: 0.4;
cursor: pointer;
}
.slider-indicator li.active {
width: 12px;
height: 12px;
opacity: 1;
}
</style>
</head>
<body>
<div class="slider">
<div class="slider-wrapper">
<img alt="" src="../img/slider01.jpg"/>
</div>
<div class="slider-footer">
<p>对人类来说会不会太超前了?</p>
<ul class="slider-indicator">
<li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<div class="toggle">
<button class="prev"><</button>
<button class="next">></button>
</div>
</div>
</div>
<script>
// 数据数组
const data = [
{url: '../img/slider01.jpg', title: '谁不想和小猫咪贴贴呢!', color: 'rgb(100, 67, 68)'},
{url: '../img/slider02.jpg', title: '开启剑与雪的黑暗传说!', color: 'rgb(43, 35, 26)'},
{url: '../img/slider03.jpg', title: '真正的jo厨出现了!', color: 'rgb(36, 31, 33)'},
{url: '../img/slider04.jpg', title: '对人类来说会不会太超前了?', color: 'rgb(139, 98, 66)'},
{url: '../img/slider05.jpg', title: '李玉刚:让世界通过B站看到东方大国文化', color: 'rgb(67, 90, 92)'},
{url: '../img/slider06.jpg', title: '快来分享你的寒假日常吧~', color: 'rgb(166, 131, 143)'},
{url: '../img/slider07.jpg', title: '哔哩哔哩小年YEAH', color: 'rgb(53, 29, 25)'},
{url: '../img/slider08.jpg', title: '一站式解决你的电脑配置问题!!!', color: 'rgb(99, 72, 114)'},
]
// 获取元素
const img = document.querySelector('.slider-wrapper img')
const p = document.querySelector('.slider-footer p')
const footer = document.querySelector('.slider-footer')
// 定义一个全局变量 记录数组序号
let i = 0
// 1. 右侧按钮
const next = document.querySelector('.next')
next.addEventListener('click', function () {
// console.log(11)
i++
i = i > 7 ? 0 : i
toggle()
})
// 2. 左侧按钮
const prev = document.querySelector('.prev')
prev.addEventListener('click', function () {
i--
i = i < 0 ? 7 : i
toggle()
})
// 3. 轮播效果
let timeId = setInterval(function () {
next.click()
}, 1500)
// 4. 鼠标移入 停止轮播图
const slider = document.querySelector('.slider')
slider.addEventListener('mouseenter', function () {
clearInterval(timeId)
console.log('stop')
})
// 5. 鼠标移除 开始轮播图
slider.addEventListener('mouseleave', function () {
timeId = setInterval(function () {
next.click()
console.log('start')
}, 1500)
})
// 渲染页面
function toggle() {
img.src = data[i].url
p.innerHTML = data[i].title
footer.style.backgroundColor = data[i].color
// 先移除之前的小圆点 再添加新的小圆点
document.querySelector(`.slider-indicator .active`).classList.remove('active')
document.querySelector(`.slider-indicator li:nth-child(${i + 1})`).classList.add('active')
}
</script>
</body>
</html>
效果展示
轮播图
焦点事件-小米搜索框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>小米搜索框</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul {
list-style: none;
}
.mi {
position: relative;
width: 223px;
margin: 100px auto;
}
.mi input {
width: 223px;
height: 48px;
padding: 0 10px;
font-size: 14px;
line-height: 48px;
border: 1px solid #e0e0e0;
outline: none;
}
.mi .search {
border: 1px solid #ff6700;
}
.result-list {
display: none;
position: absolute;
left: 0;
top: 48px;
width: 223px;
border: 1px solid #ff6700;
border-top: 0;
background: #fff;
}
.result-list a {
display: block;
padding: 6px 15px;
font-size: 12px;
color: #424242;
text-decoration: none;
}
.result-list a:hover {
background-color: #eee;
}
</style>
</head>
<body>
<div class="mi">
<input placeholder="小米笔记本" type="search">
<ul class="result-list">
<li><a href="#">全部商品</a></li>
<li><a href="#">小米11</a></li>
<li><a href="#">小米10S</a></li>
<li><a href="#">小米笔记本</a></li>
<li><a href="#">小米手机</a></li>
<li><a href="#">黑鲨4</a></li>
<li><a href="#">空调</a></li>
</ul>
</div>
<script>
// 属性选择器
// 获取搜索框
const input = document.querySelector('[type = search]')
// 获取下拉列表
const ul = document.querySelector('.result-list')
// 获得焦点事件
input.addEventListener('focus', function () {
ul.style.display = 'block'
// 获得焦点显示边框
input.classList.add('search')
})
// 失去焦点事件
input.addEventListener('blur', function () {
ul.style.display = 'none'
input.classList.remove('search')
})
</script>
</body>
</html>
效果展示
小米搜索框
事件对象-评论回车发布案例
需求:按下回车键盘,可以发布信息
分析:
①:用到按下键盘事件 keydown 或者 keyup 都可以
②:如果用户按下的是回车键盘,则发布信息
③:让留言信息模块显示,把拿到的数据渲染到对应标签内部
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>发表评论案例</title>
<style>
.wrapper {
min-width: 400px;
max-width: 800px;
display: flex;
justify-content: flex-end;
}
.avatar {
width: 48px;
height: 48px;
border-radius: 50%;
overflow: hidden;
background: url(../img/avatar.jpg) no-repeat center / cover;
margin-right: 20px;
}
.wrapper textarea {
outline: none;
border-color: transparent;
resize: none;
background: #f5f5f5;
border-radius: 4px;
flex: 1;
padding: 10px;
transition: all 0.5s;
height: 30px;
}
.wrapper textarea:focus {
border-color: #e4e4e4;
background: #fff;
height: 50px;
}
.wrapper button {
background: #00aeec;
color: #fff;
border: none;
border-radius: 4px;
margin-left: 10px;
width: 70px;
cursor: pointer;
}
.wrapper .total {
margin-right: 80px;
color: #999;
margin-top: 5px;
opacity: 0;
transition: all 0.5s;
}
.list {
min-width: 400px;
max-width: 800px;
display: flex;
}
.list .item {
width: 100%;
display: flex;
}
.list .item .info {
flex: 1;
border-bottom: 1px dashed #e4e4e4;
padding-bottom: 10px;
}
.list .item p {
margin: 0;
}
.list .item .name {
color: #FB7299;
font-size: 14px;
font-weight: bold;
}
.list .item .text {
color: #333;
padding: 10px 0;
}
.list .item .time {
color: #999;
font-size: 12px;
}
</style>
</head>
<body>
<div class="wrapper">
<i class="avatar"></i>
<textarea id="tx" maxlength="200" placeholder="发一条友善的评论" rows="2"></textarea>
<button>发布</button>
</div>
<div class="wrapper">
<span class="total">0/200字</span>
</div>
<div class="list">
<div class="item" style="display: none;">
<i class="avatar"></i>
<div class="info">
<p class="name">清风徐来</p>
<p class="text">大家都辛苦啦,感谢各位大大的努力,能圆满完成真是太好了[笑哭][支持]</p>
<p class="time">2022-10-10 20:29:21</p>
</div>
</div>
</div>
<script>
// 1. 当文本域获得焦点,就让total显示出来
const tx = document.querySelector('#tx')
const total = document.querySelector('.total')
tx.addEventListener('focus', function () {
total.style.opacity = '1'
})
// 2. 当文本域失去焦点,就让total隐藏起来
tx.addEventListener('blur', function () {
total.style.opacity = '0'
})
// 3. 检测用户输出
tx.addEventListener('input', function () {
// 获取输入字符串的长度
total.innerHTML = `${tx.value.length}/200字`
})
// 4. 按下回车发布评论
const item = document.querySelector('.item')
const text = document.querySelector('.text')
tx.addEventListener('keyup', function (e) {
// 大写Enter
if (e.key === 'Enter') {
// 输入的内容不为空时才能发布
// trim() 去掉字符串两边的空格
// 或者tx.value.trim() !== ''
if (tx.value.trim()) {
text.innerHTML = tx.value
item.style.display = 'block'
}
// 清空文本框
tx.value = ''
// 按下回车 ,重置字数
total.innerHTML = '0/200字'
}
})
</script>
</body>
</html>
效果展示
回车评论
即使输入的不全是空格,输入的空格也会被处理,这跟html/css有关
tab切换
需求:鼠标停放在不同的菜单,显示不同的内容
分析:
①:主要核心是类的切换, 设定一个当前类,可以让当前元素高亮
②:鼠标经过当前选项卡,先移除其余元素身上的当前类,而只给当前元素添加类
③:注意,当前类只能有一个
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta content="IE=edge" http-equiv="X-UA-Compatible"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>tab栏切换</title>
<style>
* {
margin: 0;
padding: 0;
}
.tab {
width: 590px;
height: 340px;
margin: 20px;
border: 1px solid #e4e4e4;
}
.tab-nav {
width: 100%;
height: 60px;
line-height: 60px;
display: flex;
justify-content: space-between;
}
.tab-nav h3 {
font-size: 24px;
font-weight: normal;
margin-left: 20px;
}
.tab-nav ul {
list-style: none;
display: flex;
justify-content: flex-end;
}
.tab-nav ul li {
margin: 0 20px;
font-size: 14px;
}
.tab-nav ul li a {
text-decoration: none;
border-bottom: 2px solid transparent;
color: #333;
}
.tab-nav ul li a.active {
border-color: #e1251b;
color: #e1251b;
}
.tab-content {
padding: 0 16px;
}
.tab-content .item {
display: none;
}
.tab-content .item.active {
display: block;
}
</style>
</head>
<body>
<div class="tab">
<div class="tab-nav">
<h3>每日特价</h3>
<ul>
<li><a class="active" href="javascript:">精选</a></li>
<li><a href="javascript:">美食</a></li>
<li><a href="javascript:">百货</a></li>
<li><a href="javascript:">个护</a></li>
<li><a href="javascript:">预告</a></li>
</ul>
</div>
<div class="tab-content">
<div class="item active"><img alt="" src="../img/tab00.png"/></div>
<div class="item"><img alt="" src="../img/tab01.png"/></div>
<div class="item"><img alt="" src="../img/tab02.png"/></div>
<div class="item"><img alt="" src="../img/tab03.png"/></div>
<div class="item"><img alt="" src="../img/tab04.png"/></div>
</div>
</div>
<script>
// 1. 为所有 a 绑定鼠标经过事件
const as = document.querySelectorAll('.tab-nav a')
for (let i = 0; i < as.length; i++) {
as[i].addEventListener('mouseenter', function () {
// 先移除 再添加
document.querySelector('.tab-nav .active').classList.remove('active')
this.classList.add('active')
// 2. 下面的内容随着变化
document.querySelector('.tab-content .active').classList.remove('active')
document.querySelector(`.tab-content div:nth-child(${i + 1})`).classList.add('active')
})
}
</script>
</body>
</html>
效果展示
tab切换
全选按钮
需求:用户点击全选,则下面复选框全部选择,取消全选则全部取消,文字对应变化
分析:
①:遍历下面的所有的checkbox,添加点击事件
②:检查小复选框选中的个数,是不是等于 小复选框总的个数,
③: 把结果给 全选按钮
④: 利用css 复选框选择器 input:checked
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>全选按钮</title>
<style>
* {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #c0c0c0;
width: 500px;
margin: 100px auto;
text-align: center;
}
th {
background-color: #09c;
font: bold 16px "微软雅黑";
color: #fff;
height: 24px;
}
td {
border: 1px solid #d0d0d0;
color: #404060;
padding: 10px;
}
.allCheck {
width: 80px;
}
input {
cursor: pointer;
}
</style>
</head>
<body>
<table>
<tr>
<th class="allCheck">
<label for="checkAll">
<input id="checkAll" name="" type="checkbox"> <span class="all">全选</span>
</label>
</th>
<th>商品</th>
<th>商家</th>
<th>价格</th>
</tr>
<tr>
<td>
<label for="ck1">
<input class="ck" id="ck1" name="check" type="checkbox">
</label>
</td>
<td>小米手机</td>
<td>小米</td>
<td>¥1999</td>
</tr>
<tr>
<td>
<label for="ck2">
<input class="ck" id="ck2" name="check" type="checkbox">
</label>
</td>
<td>小米净水器</td>
<td>小米</td>
<td>¥4999</td>
</tr>
<tr>
<td>
<label for="ck3">
<input class="ck" id="ck3" name="check" type="checkbox">
</label>
</td>
<td>小米电视</td>
<td>小米</td>
<td>¥5999</td>
</tr>
</table>
<script>
// 1. 获取大复选框
const checkAll = document.querySelector('#checkAll')
// 2. 获取小复选框
const cks = document.querySelectorAll('.ck')
// 3. 大复选框点击事件
checkAll.addEventListener('click', function () {
for (let i = 0; i < cks.length; i++) {
cks[i].checked = this.checked
// console.log(cks[i].disabled)
// console.log(checkAll.disabled)
}
})
// 5. 小复选框控制大复选框
for (let i = 0; i < cks.length; i++) {
cks[i].addEventListener('click', function () {
// 判断选中的小复选框 是不是等于 总的小复选框个数
checkAll.checked = document.querySelectorAll('.ck:checked').length === cks.length;
}
)
}
</script>
</body>
</html>
效果展示
复选框