这里是学习webapi的dom,不是学h5与c3,为了不让代码太繁琐复杂,案例中的一些css我会写的很简单,体现出bom的知识点即可。
事件
什么是事件?用户点击了一下控件,或者键盘按下,鼠标经过等都是事件。
事件记得引号,事件一般都是小写。
后面的匿名函数,写成一个函数名也行。
<body>
<button>
点我
</button>
<script>
let btn =document.querySelector("button")
function demo() {
alert("被点击了")
}
btn.addEventListener('click',demo)
</script>
</body>
点击关闭图片案例
<style>
* {
margin: 0;
padding: 0;
}
span {
display: inline-block;
width: 20px;
height: 20px;
border: 1px solid black;
vertical-align: top;
line-height: 20px;
text-align: center;
}
</style>
<body>
<div>
<span>x</span>
<img src="./6.jpg" alt="">
</div>
<script>
let span = document.querySelector('span')
let img = document.querySelector('img')
span.addEventListener('click', function () {
img.style.display = 'none'
})
</script>
</body>
事件类型有click,mouseenter,mouseleave,keydown,keyup,blur,focus,input等等等等,注意事件一般都是小写。
<!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>
.main{
border: 1px solid #ccc;
width: 400px;
height: 200px;
margin: 0 auto;
padding: 20px;
/* background-color: pink; */
}
.head{
height: 50px;
/* background-color: blue; */
z-index: 1;
padding-left: 150px;
}
.name{
font-size: 20px;
color: red;
line-height: 50px;
height: 50px;
}
button{
width: 80px;
}
.button{
display: flex;
justify-content: space-around;
margin-top: 30px;
}
</style>
</head>
<body>
<div class="main">
<div class="head">
<p><strong>随机点名</strong></p>
</div>
<div class="content">
<span><strong>名字是:</strong></span>
<span class="name">瑾年</span>
</div>
<div class="button">
<button>开始</button>
<button>结束</button>
</div>
</div>
<script>
let names=['瑾年','周东奇','张三','李四'];
let name=document.querySelector('.name');
let start=document.querySelector('button:first-child');
let end=document.querySelector('button:last-child');
let timer = 0
let random = 0
start.addEventListener('click',function(){
// 定时器间歇函数,让名字随机变化
timer = setInterval(function(){
random=Math.floor(Math.random()*names.length)
name.innerHTML=names[random];
},100)
names.splice(random,1)
if(names.length==0){
alert('没有名字了')
clearInterval(timer)
}
})
end.addEventListener('click',function(){
clearInterval(timer);
})
</script>
</body>
</html>
注意,因为作用域的问题,timer和random需要在全局就声明好
老版本事件写法
<body>
<button>点我</button>
<script>
let btn =document.querySelector('button')
btn.onclick = function(){
alert('我是老版本的写法')
}
</script>
</body>
小米搜索框
使用blur和focus事件。(失去焦点和取得焦点,这个焦点需要鼠标点击才有)
也可以用mouseleave和mouseenter,鼠标在上面就行
tips:属性值选择器,以前很少用
如此案例中的input[type=search]就是选择类型是search的input选择器
a[href]就是选择所有设置了href的超链接。
教程参考:https://blog.csdn.net/nicepainkiller/article/details/116132605
https://www.w3school.com.cn/css/css_selector_attribute.asp
<!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>
* {
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;
transition: all .5s
}
.mi .search {
border: 1px solid #ff6700;
}
.result-list {
position: absolute;
left: 0;
top: 48px;
width: 223px;
border: 1px solid #ff6700;
border-top: 0;
background: #fff;
display: none;
}
.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 type="search" placeholder="小米笔记本">
<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('.mi input');
const resultList = document.querySelector('.result-list');
input.addEventListener('mouseenter', function () {
resultList.style.display = 'block';
input.classList.add('search');
})
input.addEventListener('mouseleave', function () {
resultList.style.display = 'none';
input.classList.remove('search');
})
</script>
</body>
</html>
微博输入案例
用户输入文字后,字数会自动统计输入了多少个。
<textarea placeholder="说点什么吧..." id="area" cols="30" rows="10" maxlength="200"></textarea>
<!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>
.main {
margin: 0 auto;
width: 900px;
}
.botton {
margin-left: 520px;
font: bold 14px '宋体';
}
button {
cursor: pointer;
background-color: skyblue;
border: none;
color: aliceblue;
}
textarea {
resize: none;
border-radius: 10px;
}
</style>
</head>
<body>
<div class="main">
<textarea name="" id="" cols="82" rows="7" maxlength="200" placeholder="你今天有什么要分享给瑾年呢?"></textarea>
<div class="botton">
<span>0</span><span>/</span><span>200</span>
<button>发布</button>
</div>
</div>
<script>
const textarea =document.querySelector('textarea')
const button =document.querySelector('button')
const text_num =document.querySelector('div span:first-child')
// 看看有没有获取到,对选择器有点不自信
// console.log(text_num)
button.addEventListener('click',function(){
alert('发布成功')
})
textarea.addEventListener('input',function(){
text_num.style.color="red"
text_num.innerHTML= textarea.value.length
button.value= textarea.value.length
console.log(button.value)
})
</script>
</body>
</html>
1-其中textarea可以设置placeholder和id和cols与rows以及maxlength,它还有一个css叫resize:none就可以禁止用户拖拉它的大小(默认是可以的)
2-input有一个readonly属性,可以只读,不可修改。
注意:
1-placeholder设置不生效的原因可能是,textarea标签之间有空格或者换行
错误:
1-在把textarea中的文字长度赋予span的时候,一直不生效,原来是把text_num.innerHTML写成了text_num.value,value是textarea,input等的属性,无法修改span的内容。把修改内容和属性记混了。
案例全选
1-当一个事件为false就把全选状态修改为false,使用return能提高性能,遇到false直接退出,减少后续的无用判断。
2-当同时给多个元素绑定相同事件,用for循环遍历。
其实就是多练习熟悉事件的语法,这些逻辑都很简单。
犯错:
1-层次不清晰,写着写着自己选择器记不得了,把获取对象后面的选择器写错,控制台也不报错,效果一直不生效。
2-注意循环中变量的声明,它们的作用域,哪些变量给了全局,哪些没有!
我自认为两个for循环可以使用一样的i,因为作用域不同,谁知道我原先定义了i为全局变量,一个bug能卡半小时找不出问题。也许这就是变量污染吧,也是立即使用函数诞生的原因。
3-所以说能使用不同变量,就使用不同的,不要以为自己对作用域很了解,最后把自己绕进去。
<!DOCTYPE html>
<html>
<head lang="en">
<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;
}
</style>
</head>
<body>
<table>
<tr>
<th class="allCheck">
<input type="checkbox" name="" id="checkAll"> <span class="all">全选</span>
</th>
<th>商品</th>
<th>商家</th>
<th>价格</th>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck">
</td>
<td>小米手机</td>
<td>小米</td>
<td>¥1999</td>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck">
</td>
<td>小米净水器</td>
<td>小米</td>
<td>¥4999</td>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck">
</td>
<td>小米电视</td>
<td>小米</td>
<td>¥5999</td>
</tr>
</table>
<script>
// 给遍历存储所有复选框的checked状态伪数组的i
let i = 0
// 全选框后的全选/取消字体
let span = document.querySelector('span')
const all = document.querySelector('#checkAll')
const cks = document.querySelectorAll('.ck')
// web计算机二级还是老写法,练一练
all.onclick = function () {
// 当全选框被点击后,子ck的checked全部变为true,再点击就全是false
for (let i = 0; i < cks.length; i++) {
cks[i].checked = all.checked
}
// 一定要放在这个函数里面,放外面的话,还没点就判断了,这个判断语句等于白写。
if (all.checked === true) {
span.innerHTML = '取消'
} else {
span.innerHTML = '全选'
}
}
// 小按钮事件
// 先遍历所有小按钮,添加监听器
for (let j = 0; j < cks.length; j++) {
console.log(cks[j])
cks[j].addEventListener('click', function () {
for (let g = 0; g < cks.length; g++) {
if (cks[g].checked == false) {
all.checked = false
span.innerHTML = '全选'
// 有一个是false,下面的小按钮就没必要再判断了
return
}
}
// 如果所有的按钮都是选中状态true,则让all.checked为true
all.checked = true
span.innerHTML = '取消'
})
}
</script>
</body>
</html>
案例购物车加减案例
input的一个css,outline:none可以去除input获取焦点后的默认样式
outline:轮廓线
注意:
1-文本框表单等取过来的值和prompt一样都是字符串型的,记得转换。
2-这里的每次加1,可以把值从字符串转换成数字再加,也可以直接用++自增,因为自增可以隐式转换。(自增自减和比较运算符==,+=,-=都有隐士转换)
<body>
<div>
<input type="text" id="total" value="1" readonly>
<input type="button" value="+" id="add">
<input type="button" value="-" id="reduce" disabled>
<script>
const total = document.querySelector('#total')
const add = document.querySelector('#add')
const reduce = document.querySelector('#reduce')
// 点加事件发生的事件函数
add.addEventListener('click',function(){
total.value++
reduce.disabled =false
})
// 点减号发生的
reduce.addEventListener('click',function(){
total.value--
if(total.value<=1){
reduce.disabled =true
}
})
</script>
</div>
</body>
高阶函数
高阶函数就是把函数当做值来对待
函数表达式
如let fn = function(){}和btn.onclick= function(){}都是函数表达式,是高阶函数的一种。
回调函数
当参数的那个函数就叫做回调函数。
环境对象
this叫做环境对象,它就是一个对象
上图第一个,因为fn()调用的全称是window.fn()所以this指向window
上图第二个因为btn对象调用了这个函数,所以this指向btn
排他思想(了解)
排他思想用于多个中只能存在一个的场景,如tab栏(只能选中一个),或者轮播图下面的小圆点(是哪张图片哪个圆点被选中,变css样式)
1-首先用for循环,把其他所有人干掉,让所有人都被生效这个样式
2-复活自己,所有人都不生效后,再给自己加上
<body>
<button>第1个</button><button>第2个</button><button>第3个</button><button>第4个</button><button>第5个</button>
<script>
let btns = document.querySelectorAll('button')
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function () {
// this.classList.add('pink')
// 干掉所有人
for (let j = 0; j < btns.length; j++) {
btns[j].classList.remove('pink')
}
// 复活我自己
this.classList.add('pink')
})
}
</script>
</body>
如上,五个按钮,选中谁,谁变粉色,先for循环让所有人都不生效粉色,然后给自己加上粉色的样式。
问题
其实一开始只会有一个生效,为了找到它,用for循环去遍历所有的,会浪费很多性能。
解决:
我们直接用document.querySelector找出哪个生效的,然后再去除即可。
然后再用this把事件加上即可。
注意
1-标签换行会有缺口,写在同一行就没有,如下
解决一:把标签写在一行,但是代码看起来凌乱
方法二:把父类font-size设置为0px,缺点是子类字体必须再设置font-size
参考https://baijiahao.baidu.com/s?id=1552352366285716&wfr=spider&for=pc
2-注意documen.querySelector和classList.add等的区别,一个是通过选择器选,一个是加类,一个带点,一个不带。如上图的pink类
综合案例tab栏
注意:
1-tab个数和页面个数必须一样,tab多了会没页面显示,页面多了会不隐藏,直接跳到下面去。
2-找选择器的时候,后代用空格隔开,如果要找的选择器有多个类,而且你需要用多个类找,需要把两个类连起来因为它们是兄弟。
思路:
js都好说,原先我的难点是四/多个内容页面,如何排在同一个地方?第一时间想到了绝对定位和浮动,因为它们脱标,再想想脱标也没用呀,照样会显示。
解决:
其实直接display:none就好了,因为是排他的,只有一个显示,所以可以多个内容在同一个地方。(其实就一个,其他的全部隐藏)
tips:
display:none不仅仅视觉上消失还脱标;visibility:hidden仅仅是视觉上消失,还占位。
<!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>
.tab .active {
background-color: pink;
transform: scale(1.2);
}
a{
display: none;
width: 300px;
height: 200px;
border: 1px solid black;
}
/* 这个active和上面的tab active不一样,虽然都是给标签添加了active类名,但是生效的css不同 */
.content .active{
display: block;
}
</style>
</head>
<body>
<div class="wraper">
<div class="tab">
<button class="active">第一个</button>
<button>第二个</button>
<button>第三个</button>
<button>第四个</button>
<button>第五个</button>
</div>
<div class="content">
<div><a class="active">第一张</a></div>
<div><a>第二张</a></div>
<div><a>第三张</a></div>
<div><a>第四张</a></div>
<div><a>第五张</a></div>
</div>
</div>
<script>
let buttons = document.querySelectorAll('button')
// 获取所有的a
let as = document.querySelectorAll('.content a')
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function () {
// 找出先前生效的,给它去除
document.querySelector('.tab .active').classList.remove('active')
// 让当前选中的生效
this.classList.add('active')
// 设置内容
// 找出先前生效的,给它去除
document.querySelector('.content .active').classList.remove('active')
// 让当前选中的生效
as[i].classList.add('active')
})
}
</script>
</body>
</html>