JS 基础
输入和输出语法
向body输出内容
document.write("<h1>眼泪为你唱歌</h1>")
窗口弹出内容
alert("将军")
控制台打印内容
console.log("勇敢的面对");
输入语句
prompt("蓝色的雨")
输入语句输出到页面
const name = prompt()
document.write(name)
变量和常量的命名
变量 用 let常量 用 const
null 和 underfined 的区别
- underfined 没有赋值
- null 赋值了, 但是内容为空
null 作为未创建的对象
显式转换
String(false) // "false" 布尔值转换为字符串
Number("123") // 123 字符串转换为数值
Boolean([]) // true 对象类型转换为布尔值
Object(123) // new Number(123) 原始值通过Number()构造函数转换为基本包装类型
案例 输入手机价格输出到页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>h5 {text-align: center;}table {margin: 0 auto;}table {border-collapse: collapse;}th , tr {border: 1px pink solid;}</style><script>let phone = prompt("请输入手机名")let price1 = +prompt("请输入单价")let num = +prompt("请输入数量")let con = prompt("请输入地址")let price2 = price1 * numdocument.write(`<h5>订单确认</h5><table><tr><th>商品名称</th><th>商品价格</th><th>商品数量</th><th>总价</th><th>收货地址</th></tr><tr><td>${phone}</td><td>${price1}元</td><td>${num}</td><td>${price2}元</td><td>${con}</td></tr></table>`)</script>
</head>
<body></body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gCf5mnXY-1690198311345)(https://imgfff-1313020458.cos.ap-shanghai.myqcloud.com/images/%E6%88%B3%E7%9C%8B%E5%91%BD%E8%BD%A6%E6%A0%87%E5%8F%B7.gif)]
+++
分支循环存钱案例
<script>// 最开始存了 100 元let money = 100while (true) {let input = +prompt("请选择操作:" +"1. 存钱" +"2. 取钱" +"3. 查看金额" +"4. 退出")if (input === 4) {break}switch (input) {case 1:let mon1 = +prompt("请输入存的金额:")money+=mon1breakcase 2:let mon2 = +prompt("请输入取的金额:")money -= mon2;breakcase 3:alert(money)break}}</script>
函数使用
定义两个重名的函数, 后面的会覆盖前面的
function f() {alert(1)
}
function f() {alert(2)
}
f()
此时打开页面, 弹窗数字 : 2
作用域
js中作用域分成全局作用域和局部作用域, 变量根据作用域来分, 分成全局变量和局部变量
函数的形参和函数内部的变量为局部变量
外部的就是全局变量
匿名函数
匿名函数直接调用有两种方法, 注意第一种后面加分号;
(function (x, y){alert(x+y)})(1,2);
// 或
(function (x, y){alert(x+y)}(1,2))
转换为 Boolean 型
’ ’ 0 undefined null false NaN 转换成布尔值是 false , 其余为 true
测试一下:
// ' ' 0 undefined null false NaN
console.log(Boolean(''));
console.log(Boolean(0));
console.log(Boolean(undefined));
console.log(Boolean(null));
console.log(Boolean(false));
console.log(Boolean(NaN));
Web APIs
前言
变量声明关键字
能用const 就用const , 如果报错了,再用 let
作用和分类
使用JS操作html和浏览器
分类: DOM 文档对象模型
BOM 浏览器对象模型
DOM 作用: 开发网页内容特效和实现用户交互, js 操作网页内容
DOM 树
文档树, 描述标签之间关系
html页面的结构不够清晰, 我们把页面变成DOM 模型
Dom 对象: 浏览器根据html标签生成的对象
document : DOM提供的一个对象, 网页所有内容都在document中
获取 DOM 元素
通过CSS 选择器, 获取DOM元素
<div class="head"><ul><li></li><li></li><li></li><li></li><li></li></ul>
</div>
<script>console.log(document.querySelector('.head'));console.log(document.querySelectorAll('ul li'));
</script>
+++
直接加点来操作元素
const head = document.querySelector('.head')
head.style.color = 'red'
而querySelectAll获取的是伪数组
, 里面只有一个元素, 可以遍历, 不能调用数组的方法
const head = document.querySelector('.head')head.style.color = 'red'const lis = document.querySelectorAll('ul li')lis[1].style.color = 'blue'
操作元素内容
innerText 方法改变字体文本内容
innerHtml 方法可以加html标签样式
<div class="box">我是盒子内容</div><script>const box = document.querySelector('.box');box.innerText = '我是你大爷'</script>
+++
innerText 不识别里面的标签
box.innerText = '<strong>我是你大爷</strong>'
+++
box.innerHTML = '<strong>我是你大爷</strong>'
+++
操作元素属性
直接加点操作
测试一个更换路径, 实现图片替换
<div class="box"><img src="gou.jpg" alt="">
</div>
<script>const element = document.querySelector('.box img')element.src = 'lianlian.jpg'
</script>
通过style 操作 css
遇到 - 转小驼峰
<div class="box"></div><script>const box = document.querySelector('.box');box.style.width = '200px'box.style.height = '200px'box.style.backgroundColor = 'pink'</script>
+++
这样通过style样式修改代码繁琐, 另一种方案:
在css代码中写好, 然后使用 document 修改类名即可, 这是我们所熟悉的
<div class="box"></div><script>const htmlDivElement = document.querySelector('div');htmlDivElement.className = 'box2'</script>
可以写多个
htmlDivElement.className = 'box box2';
这样有一个覆盖问题, 引出下一个方法
<script>const htmlDivElement = document.querySelector('div');// 追加htmlDivElement.classList.add('.box2')// 删除htmlDivElement.classList.remove('.box2')// 切换htmlDivElement.classList.toggle('.box2')
</script>
className 和 classList 的区别就是初王和第二代王
操作表单元素属性
表单元素操作方式一样的
选中input的value可以获取值
自定义属性
以 data- 开头的属性
<div><ul><li data-id="1" data-spm="sm"></li><li data-id="2"></li><li data-id="3"></li><li data-id="4"></li><li data-id="5"></li></ul></div><script>const htmlDivElement = document.querySelector('li');console.log(htmlDivElement.dataset.id); // 1console.log(htmlDivElement.dataset.spm); // sm</script>
+++
定时器 间歇函数
setTimeout 延时时间到了, 调用回调函数
<button>点击停止定时器</button><script>const htmlButtonElement = document.querySelector('button');let f = setTimeout(function () {alert('我是神皮')}, 5000)htmlButtonElement.addEventListener("click",function () {clearTimeout(f)})</script>
这个函数, 5s调用仅一次, 提前点击按钮可以阻止调用函数
+++
setInterval 每隔这个延时时间会调用回调函数, 重复调用
function show() {console.log("找到工作");}setInterval(show, 1000);
+++
配合变量和回调函数使用
<button>点击停止定时器</button><script>let a = 1let setInter = setInterval(function () {a++console.log(a);}, 200)const htmlButtonElement = document.querySelector('button');htmlButtonElement.addEventListener("click", function () {clearInterval(setInter)})</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WeGzTFfs-1690198311349)(https://imgfff-1313020458.cos.ap-shanghai.myqcloud.com/images/%E5%B7%A5%E9%9E%A5%E6%90%AC%E7%A0%96.gif)]
+++
倒计时效果
<body><textarea cols="30" id="" name="" rows="10">用户注册协议欢迎注册成为京东用户!在您注册过程中,您需要完成我们的注册流程并通过点击同意的形式在线签署以下协议,请您务必仔细阅读、充分理解协议中的条款内容后再点击同意(尤其是以粗体或下划线标识的条款,因为这些条款可能会明确您应履行的义务或对您的权利有所限制)。【请您注意】如果您不同意以下协议全部或任何条款约定,请您停止注册。您停止注册后将仅可以浏览我们的商品信息但无法享受我们的产品或服务。如您按照注册流程提示填写信息,阅读并点击同意上述协议且完成全部注册流程后,即表示您已充分阅读、理解并接受协议的全部内容,并表明您同意我们可以依据协议内容来处理您的个人信息,并同意我们将您的订单信息共享给为完成此订单所必须的第三方合作方(详情查看</textarea><br><button class="btn" disabled>我已经阅读用户协议(6)</button><script>let element = document.querySelector('.btn');let i = 6let inter = setInterval(function () {i--element.innerHTML = `我已经阅读用户协议(${i})`if (i === 0) {clearInterval(inter)element.disabled = falseelement.innerText = `注册成功`}}, 1000)</script>
</body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bpS4Gt0n-1690198311349)(https://imgfff-1313020458.cos.ap-shanghai.myqcloud.com/images/%E5%A4%8D%E6%B5%8B%E8%A7%84%E8%8C%83.gif)]
+++
事件监听
概念: 让程序检测是否有事件产生, 一旦有事件触发, 立即调用一个函数做出
响应, 也叫绑定事件或注册事件, 比如鼠标经过显示下拉菜单, 点击可以播放轮播图等等
对象.addEventListener(‘事件类型’, 要执行的函数 )
事件监听三要素:
- 事件源: 哪个dom元素被事件触发, 获取这个dom元素
- 事件类型: 用什么方式触发, 比如鼠标单击, 鼠标经过
- 事件调用的函数, 要做什么事
随机点名案例
<h3>随机点名</h3>
<div>名字是:<span class="name">这里显示名字</span>
</div>
<button class="btn1">开始</button>
<button class="btn2">结束</button><script>const array = ['张飞', '关羽', '赵云', '马超', '黄忠'];const name = document.querySelector(".name");const btn1 = document.querySelector(".btn1");const btn2 = document.querySelector(".btn2");function getRandom(min, max) {return Math.floor(Math.random() * (max - min + 1)) + min}let demo;btn1.addEventListener('click',function () {demo = setInterval(function () {let random = getRandom(0, 4);name.innerText = array[random]}, 100)})btn2.addEventListener('click', function () {clearInterval(demo)})</script>
+++
事件类型
鼠标事件
鼠标触发 click mouseenter mouseleave
焦点事件
表单获得光标 focus blur
键盘事件
键盘触发 keydown keyup
文本事件
表单输入触发 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>* {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 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 element = document.querySelector('[type=search]');const element1 = document.querySelector('.result-list');element.addEventListener('focus', function () {element1.style.display = 'block'})element.addEventListener('blur', function () {element1.style.display = 'none'})</script>
</body></html>
+++
事件对象
事件绑定的回调函数的第一个参数是事件对象, 取名为e
元素.addEventListener('click', function(e) {
})
回车键打印内容
<input type="text">
<script>const htmlInputElement = document.querySelector('input');htmlInputElement.addEventListener('keyup', function (e) {if (e.key === 'Enter')console.log("你按下了回车键");})
</script>
案例 bilibili发布评论
<!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>评论回车发布</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;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>const element = document.querySelector('#tx');const element1 = document.querySelector('.item');const element2 = document.querySelector('.text');element.addEventListener('keyup', function (e) {if (e.key === 'Enter') {element1.style.display = 'block'element2.innerText = element.innerText}})
</script></body>
</html>
环境对象
函数内部特殊的变量 this , 代表当前函数运行时所处的环境
this指向规则: 谁调用这个函数, this 就指向谁
element.addEventListener('keyup', function (e) {if (e.key === 'Enter') {element1.style.display = 'block'element2.innerText = element.innerText}})
此时 element 可以替换为 this
因为 element 调用了函数
回调函数
把函数A 作为函数B的 参数, 函数A为回调函数
<script>function fn() {console.log("我是回调");}setInterval(fn, 1000)
</script>
案例 tab栏切换
<!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>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 src="./images/tab00.png" alt="" /></div><div class="item"><img src="./images/tab01.png" alt="" /></div><div class="item"><img src="./images/tab02.png" alt="" /></div><div class="item"><img src="./images/tab03.png" alt="" /></div><div class="item"><img src="./images/tab04.png" alt="" /></div></div></div><script>// 1. a 模块制作 要给 5个链接绑定鼠标经过事件// 1.1 获取 a 元素 const as = document.querySelectorAll('.tab-nav a')// console.log(as) for (let i = 0; i < as.length; i++) {// console.log(as[i])// 要给 5个链接绑定鼠标经过事件as[i].addEventListener('mouseenter', function () {// console.log('鼠标经过')// 排他思想 // 干掉别人 移除类activedocument.querySelector('.tab-nav .active').classList.remove('active')// 我登基 我添加类 active this 当前的那个 a this.classList.add('active')// 下面5个大盒子 一一对应 .item // 干掉别人document.querySelector('.tab-content .active').classList.remove('active')// 对应序号的那个 item 显示 添加 active 类document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')})}</script>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zirEsczn-1690198311351)(https://imgfff-1313020458.cos.ap-shanghai.myqcloud.com/images/%E6%94%BE%E7%9D%80%E8%B5%9B%E7%9B%B4%E6%92%AD.gif)]
+++
案例: 单选和全选
<!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>// 1. 获取大复选框const checkAll = document.querySelector('#checkAll')// 2. 获取所有的小复选框const cks = document.querySelectorAll('.ck')// 3. 点击大复选框 注册事件checkAll.addEventListener('click', function () {// 得到当前大复选框的选中状态// console.log(checkAll.checked) // 得到 是 true 或者是 false// 4. 遍历所有的小复选框 让小复选框的checked = 大复选框的 checkedfor (let i = 0; i < cks.length; i++) {cks[i].checked = this.checked}})// 5. 小复选框控制大复选框for (let i = 0; i < cks.length; i++) {// 5.1 给所有的小复选框添加点击事件cks[i].addEventListener('click', function () {// 判断选中的小复选框个数 是不是等于 总的小复选框个数// 一定要写到点击里面,因为每次要获得最新的个数// console.log(document.querySelectorAll('.ck:checked').length)// console.log(document.querySelectorAll('.ck:checked').length === cks.length)checkAll.checked = document.querySelectorAll('.ck:checked').length === cks.length})}</script>
</body></html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-64I7GUQ3-1690198311352)(https://imgfff-1313020458.cos.ap-shanghai.myqcloud.com/images/%E5%8F%91%E4%B8%ADe%E5%AF%B9%E4%B8%AA.gif)]
+++
事件流
事件完整执行过程流动路径
有捕获阶段和冒泡阶段
const man = document.querySelector('.man');const son = document.querySelector('.son');man.addEventListener('click', function () {alert("我是父亲")})son.addEventListener('click', function () {alert("我是儿子")})document.addEventListener('click', function () {alert("i need help")})<div class="man"><div class="son"></div></div>
此时是冒泡流, 从小到大
+++
给 Listener 加一个参数 true, 此时是捕获流(不常用), 效果和冒泡流相反
man.addEventListener('click', function () {alert("我是父亲")}, true)son.addEventListener('click', function () {alert("我是儿子")}, true)document.addEventListener('click', function () {alert("i need help")}, true)
+++
阻止冒泡(流动)
e.stopPropagation()
son.addEventListener('click', function (e) {alert("我是儿子")e.stopPropagation()
})
这样就只会显示自身
+++
事件解绑
匿名函数无法解绑, 因此我们必须给函数一个名字
改造上面的儿子函数
son.addEventListener('click', function (e) {alert("我是儿子")e.stopPropagation()
})
改造后 =>
let isSon;son.addEventListener('click', isSon = function (e) {alert("我是儿子")e.stopPropagation()})son.removeEventListener('click', isSon)
两种鼠标经过事件的区别
事件委托
九子夺嫡, 你要办事情, 找阿哥, 儿子再找康熙, 康熙直接给所有儿子传旨
原理: 给父元素(康熙)注册事件, 触发子元素,
冒泡
到父元素身上, 触发父元素事件
示例:
<body><ul><li>大阿哥</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul><script>document.querySelector('ul').addEventListener('click', function () {alert('123')})</script>
案例 tab栏切换 plus
<!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>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:" data-id="0">精选</a></li><li><a href="javascript:" data-id="1">美食</a></li><li><a href="javascript:" data-id="2">百货</a></li><li><a href="javascript:" data-id="3">个护</a></li><li><a href="javascript:" data-id="4">预告</a></li></ul></div><div class="tab-content"><div class="item active"><img src="./images/tab00.png" alt="" /></div><div class="item"><img src="./images/tab01.png" alt="" /></div><div class="item"><img src="./images/tab02.png" alt="" /></div><div class="item"><img src="./images/tab03.png" alt="" /></div><div class="item"><img src="./images/tab04.png" alt="" /></div></div>
</div>
<script>// 采取事件委托的形式 tab栏切换// 1. 获取 ul 父元素 因为 ul只有一个const ul = document.querySelector('.tab-nav ul')// 获取 5个 itemconst items = document.querySelectorAll('.tab-content .item')// 2. 添加事件ul.addEventListener('click', function (e) {// console.log(e.target) // e.target是我们点击的对象// 我们只有点击了 a 才会 进行 添加类和删除类操作// console.log(e.target.tagName) // e.target.tagName 点击那个对象的 标签名if (e.target.tagName === 'A') {// console.log('我选的是a')// 排他思想 ,先移除原来的activedocument.querySelector('.tab-nav .active').classList.remove('active')//当前元素添加 active 是 e.target// this 指向ul 不能用thise.target.classList.add('active')// 下面大盒子模块// console.log(e.target.dataset.id)const i = +e.target.dataset.id// 排他思想 ,先移除原来的activedocument.querySelector('.tab-content .active').classList.remove('active')// 对应的大盒子 添加 active// document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')items[i].classList.add('active')}})
</script>
</body></html>
阻止元素默认行为
e.preventDefault()
<form action="https://www.baidu.com"><input type="submit" value="免费注册"></form><script>const form = document.querySelector('form');form.addEventListener('click', function (e) {e.preventDefault() // 禁止跳转})</script>
此时点击这个页面是不会跳转的
其他事件
页面加载事件
为了把
+++
滚动事件
window.addEventListener('scroll', function () {alert('我滚动了')})
通过检测页面滚动显示元素
<body style="height: 5000px;">
<img src="gou.jpg" alt="" style="display: none"><script>window.addEventListener('scroll', function () {if (document.documentElement.scrollTop >= 500)document.querySelector('img').style.display = 'block'})
</script>
</body>
这里滚动条上方空出 500px 则显示图片
offset 家族
计算元素相对父级元素{通常为body}的距离
示例:
const one = document.querySelector('.one');console.log(one.offsetTop); // 距离页面顶部距离console.log(one.offsetLeft);// 距离页面左边距离
日期对象使用
let date = new Date();
let s = date.toLocaleString();
console.log(s);
2023/7/23 10:42:12
时间戳
1970年1月1日0时0分0秒到现在的
毫秒数
console.log(Date.now());
console.log(new Date().getTime());
console.log(+new Date());[常用]
时间戳实现倒计时
<!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>.countdown {width: 240px;height: 305px;text-align: center;line-height: 1;color: #fff;background-color: brown;/* background-size: 240px; *//* float: left; */overflow: hidden;}.countdown .next {font-size: 16px;margin: 25px 0 14px;}.countdown .title {font-size: 33px;}.countdown .tips {margin-top: 80px;font-size: 23px;}.countdown small {font-size: 17px;}.countdown .clock {width: 142px;margin: 18px auto 0;overflow: hidden;}.countdown .clock span,.countdown .clock i {display: block;text-align: center;line-height: 34px;font-size: 23px;float: left;}.countdown .clock span {width: 34px;height: 34px;border-radius: 2px;background-color: #303430;}.countdown .clock i {width: 20px;font-style: normal;}</style>
</head><body>
<div class="countdown"><p class="next">今天是2222年2月22日</p><p class="title">下班倒计时</p><p class="clock"><span id="hour">00</span><i>:</i><span id="minutes">25</span><i>:</i><span id="scond">20</span></p><p class="tips">18:30:00下课</p>
</div>
<script>// 随机颜色函数// 1. 自定义一个随机颜色函数function getRandomColor(flag = true) {if (flag) {// 3. 如果是true 则返回 #fffffflet str = '#'let arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']// 利用for循环随机抽6次 累加到 str里面for (let i = 1; i <= 6; i++) {// 每次要随机从数组里面抽取一个// random 是数组的索引号 是随机的let random = Math.floor(Math.random() * arr.length)// str = str + arr[random]str += arr[random]}return str} else {// 4. 否则是 false 则返回 rgb(255,255,255)let r = Math.floor(Math.random() * 256) // 55let g = Math.floor(Math.random() * 256) // 89let b = Math.floor(Math.random() * 256) // 255return `rgb(${r},${g},${b})`}}// 页面刷新随机得到颜色const countdown = document.querySelector('.countdown')countdown.style.backgroundColor = getRandomColor()// 函数封装 getCountTimefunction getCountTime() {// 1. 得到当前的时间戳const now = +new Date()// 2. 得到将来的时间戳const last = +new Date('2024-4-1 18:30:00')// console.log(now, last)// 3. 得到剩余的时间戳 count 记得转换为 秒数const count = (last - now) / 1000// console.log(count)// 4. 转换为时分秒// h = parseInt(总秒数 / 60 / 60 % 24) // 计算小时// m = parseInt(总秒数 / 60 % 60); // 计算分数// s = parseInt(总秒数 % 60);// let d = parseInt(count / 60 / 60 / 24) // 计算当前秒数let h = parseInt(count / 60 / 60 % 24)h = h < 10 ? '0' + h : hlet m = parseInt(count / 60 % 60)m = m < 10 ? '0' + m : mlet s = parseInt(count % 60)s = s < 10 ? '0' + s : sconsole.log(h, m, s)// 5. 把时分秒写到对应的盒子里面document.querySelector('#hour').innerHTML = hdocument.querySelector('#minutes').innerHTML = mdocument.querySelector('#scond').innerHTML = s}// 先调用一次getCountTime()// 开启定时器setInterval(getCountTime, 1000)
</script>
</body>
</html>
父子兄弟节点
查找父节点 parentNode
查找所有子节点 children
查找哥哥节点 previousElementSibling
查找弟弟节点 nextElementSibling
<body><div style="width: 500px">康熙<div class="oneSon">大阿哥</div><div class="twoSon">太子</div><div class="threeSon">三阿哥</div><div class="fourSon">雍正<div>章总</div></div><div class="fiveSon">五阿哥</div></div>
<script>const c4 = document.querySelector('.fourSon');console.log(c4.parentNode.innerText); // 康熙for (let i = 0; i < c4.parentNode.children.length; i++) { // 得到伪数组c4.parentNode.children[i].style.color = 'red';}console.log(c4.previousElementSibling.innerText); // 三console.log(c4.nextElementSibling.innerText); // 五
</script>
+++
增删节点
创建节点
document.createElement
添加节点
e.appendChild
克隆节点
e.children[0].cloneNode(true) 克隆标签和内容
e.children[0].cloneNode() 只克隆标签
删除节点
e.removeChild(li1)
M端事件 了解
触屏事件 触摸 滑动 移开
文档
Swiper中文网-轮播图幻灯片js插件,H5页面前端开发
Window 对象
BOM
浏览器对象模型, dom是bom的一部分
延时函数
setTimeOut
五秒后关闭图片
<body><img src="images/slider01.jpg"><script>const htmlImageElement = document.querySelector('img');setTimeout(function () {htmlImageElement.style.display = 'none'}, 5000)
</script>
location 对象
页面跳转
<script>location.href = 'http://www.baidu.com'
</script>
navigator
自动跳转到移动端
<!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><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 () { })();!function () { }()</script>
</head><body>这是pc端的页面<script>// (function () { })()</script>
</body></html>
单独拆出来js代码
<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 () { })();!function () { }()</script>
本地存储
浏览器的数据库
容量 5M : sessionMessage | localStorage
https://todomvc.com/examples/vanilla-es6/
localStorage
数据永久存到电脑, 除非手动删除, 否则一直都在
键值对存储
localStorage.setItem(key, value )
localStorage.setItem('黑剑', '玛利喀斯')console.log(localStorage.getItem('黑剑'));localStorage.removeItem('黑剑')
sessionStorage
关闭浏览器即消失[session], 用法和 localStorage 一样
+++
存复杂数据 [ JSON ]
const goods = {name: '小米',price: 2000}localStorage.setItem('goods', JSON.stringify(goods))console.log(JSON.parse(localStorage.getItem('goods')));
+++
map方法
map遍历数组处理数据, 返回新的数组
const arr = ['黑剑', '莲莲', '菈妮', '玛琳娜']
const arr1 = arr.map(function (ele, index) {console.log(ele);console.log(index);return 'boss: ' + ele
})
console.log(arr);
console.log(arr1);
map有返回值, forEach无返回值
join方法
把数组转换成字符串
const arr = ['黑剑', '莲莲', '菈妮', '玛琳娜']
console.log(arr);
console.log(arr.join(''));
+++
正则表达式
正则用 chatgpt 即可
const text = '这年头,总有些人,觉得自己读了两本书,识了几个字'
const reg = /两本书/
console.log(reg.test(text)); // 返回布尔console.log(reg.exec(text)); // 返回数组
true+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
['两本书',index: 15,input: '这年头,总有些人,觉得自己读了两本书,识了几个字',groups: undefined
]
元字符
reg 就是元字符, 是正则通配符格式
const text = 'dbbbbbbbbbbbbbbbbbbbbbbbbbd'
//以字母 "d" 开始和结束的字符串,中间可以包含一个或多个连续的字母 "b"
const reg = /d(b+)d/
console.log(reg.test(text)); // 返回布尔
console.log(reg.exec(text)); // 返回数组
正则匹配规则查表
形式 | 匹配规则 |
---|---|
\d | 一个数字 |
\w | 一个字母或数字 |
. | 任意字符 {py.} => {[py1], [pyt], [py?]} |
* | 任意个字符(含0) |
+ | 至少一个字符 |
? | 0或1个字符 |
{n} | n个字符 |
{n, m} | n~m个字符 |
[] | 范围 |
[a-zA-Z_] [0-9a-zA-Z_] {0, 19} | [a-zA-Z_][0-9a-zA-Z_]{0, 19} |
(P|p)ython | Python或python |
^\d | 数字开头 |
\d$ | 数字结束 |
^py$ | py |
Python 正则 re模块
import re# r 可以避免转义
print(re.match(r'\d{3}-\d{3,8}$', '010-12345'))# 识别连续空格, 无论多少个空格都能正常分割
print(re.split(r'\s+', 'ab c'))
分组
# 分组, 这里用()把reg分成两组
reg = r'^(\d{3})-(\d{3,8})$'
m = re.match(reg, '010-12345')
print(m.group(0))
print(m.group(1))
print(m.group(2))
# 010-12345
# 010
# 12345
js 进阶
动态参数 arguments
const name = ['黑剑', '莲莲', '菈妮', '玛琳娜']function f() {for (let i = 0; i < arguments.length; i++) {console.log(arguments[i]);}
}f(name)
剩余参数 …arr
const name = ['黑剑', '莲莲', '菈妮', '玛琳娜']function f(...arr) {for (let i = 0; i < arr.length; i++) {console.log(arguments[i]);}
}f(name)
箭头函数
就是 lambda 表达式
没有this arguments super 等等属性, 箭头函数适用于本来需要匿名函数的地方, 也就是lambda表达式
const name = ['黑剑', '莲莲', '菈妮', '玛琳娜']console.log(name.map(function (name) {return name.length
}));console.log(name.map(name => name.length));
箭头函数使用三元运算符
let simple = a => a > 15 ? 15 : a;
console.log(simple(16)); // 15
console.log(simple(10));// 10
let max = (a, b) => a > b ? a : b;
console.log(max(1, 2)); // 2
数组对象解构
const pig =[{name: '莲莲', age: 18, sex: '女'},{name1: '黑剑', age1: 18, sex1: '男'},
]
const [{name, age, sex},{name1, age1, sex1}] = pigconsole.log(name)
console.log(name1)
console.log(age)
console.log(age1)
console.log(sex)
console.log(sex1)
++++
原型对象prototype
函数挂载, prototype操作的是函数, 挂载的是对象
function f() {
}
f.prototype.sing = ()=>console.log('sing')
const f1 = new f();
f1.sing()
继承
const Person = {name: '莲莲',age: 18
}function Woman (){}
Woman.prototype = Person
var woman = new Woman();
console.log(woman.name);
console.log(woman.age);
+++
浅拷贝
拷贝对象
Object.assign
const Person = {name: '莲莲',age: 18
}
let o = {};
// 拷贝对象
Object.assign(o, Person)
console.log(o.name);//莲莲
console.log(o.age);//18
拷贝数组
Array.prototype.concat
// 拷贝数组
arr = [1, '黑剑', 2, true]
arr1 = Array.prototype.concat(arr)
console.log(arr1[1]);//黑剑
深拷贝
const Person = {name: '莲莲',age: 18
}
let o = {};
// 拷贝对象
function deepCopy(newObj, oldObj) {for (let k in oldObj) {newObj[k] = oldObj[k]}return newObj
}const deepCopy1 = deepCopy(o, Person);
console.log(deepCopy1);
{ name: '莲莲', age: 18 }
+++
)
### 剩余参数 ...arr```js
const name = ['黑剑', '莲莲', '菈妮', '玛琳娜']function f(...arr) {for (let i = 0; i < arr.length; i++) {console.log(arguments[i]);}
}f(name)
箭头函数
就是 lambda 表达式
没有this arguments super 等等属性, 箭头函数适用于本来需要匿名函数的地方, 也就是lambda表达式
const name = ['黑剑', '莲莲', '菈妮', '玛琳娜']console.log(name.map(function (name) {return name.length
}));console.log(name.map(name => name.length));
箭头函数使用三元运算符
let simple = a => a > 15 ? 15 : a;
console.log(simple(16)); // 15
console.log(simple(10));// 10
let max = (a, b) => a > b ? a : b;
console.log(max(1, 2)); // 2
数组对象解构
const pig =[{name: '莲莲', age: 18, sex: '女'},{name1: '黑剑', age1: 18, sex1: '男'},
]
const [{name, age, sex},{name1, age1, sex1}] = pigconsole.log(name)
console.log(name1)
console.log(age)
console.log(age1)
console.log(sex)
console.log(sex1)
++++
原型对象prototype
函数挂载, prototype操作的是函数, 挂载的是对象
function f() {
}
f.prototype.sing = ()=>console.log('sing')
const f1 = new f();
f1.sing()
继承
const Person = {name: '莲莲',age: 18
}function Woman (){}
Woman.prototype = Person
var woman = new Woman();
console.log(woman.name);
console.log(woman.age);
+++
浅拷贝
拷贝对象
Object.assign
const Person = {name: '莲莲',age: 18
}
let o = {};
// 拷贝对象
Object.assign(o, Person)
console.log(o.name);//莲莲
console.log(o.age);//18
拷贝数组
Array.prototype.concat
// 拷贝数组
arr = [1, '黑剑', 2, true]
arr1 = Array.prototype.concat(arr)
console.log(arr1[1]);//黑剑
深拷贝
const Person = {name: '莲莲',age: 18
}
let o = {};
// 拷贝对象
function deepCopy(newObj, oldObj) {for (let k in oldObj) {newObj[k] = oldObj[k]}return newObj
}const deepCopy1 = deepCopy(o, Person);
console.log(deepCopy1);
{ name: '莲莲', age: 18 }
+++