1.web API基础认知
1-1.作用:
就是使用 JS 去操作 html 和浏览器
1-2.分类:
DOM (文档对象模型)、BOM(浏览器对象模型
1-3.什么是DOM
-
DOM(Document Object Model——文档对象模型)是用来呈现以及与任意 HTML 或 XML文档交互的API
-
白话文:DOM是浏览器提供的一套专门用来操作网页内容的功能
-
DOM作用:开发网页内容特效和实现用户交互
1-4.DOM树
-
概念:
- 将 HTML 文档以树状结构直观的表现出来,我们称之为文档树或 DOM 树
- 描述网页内容关系的名词
- 作用:文档树直观的体现了标签与标签之间的关系
1-5.DOM对象(重要)
- DOM对象:浏览器根据html标签生成的 JS对象
- 所有的标签属性都可以在这个对象上面找到
- 修改这个对象的属性会自动映射到标签身上
- DOM的核心思想
- 把网页内容当做对象来处理
- document 对象
- 是 DOM 里提供的一个对象
- 所以它提供的属性和方法都是用来访问和操作网页内容的
- 网页所有内容都在document里面
2.获取DOM对象
2-1选择匹配的第一个元素
语法
参数
包含一个或多个有效的CSS选择器 字符串
返回值:
- CSS选择器匹配的第一个元素,一个 HTMLElement对象
- 如果没有匹配到,则返回null
2-2选择匹配的多个元素
语法:
参数:
- 包含一个多多个有效的css选择器字符串
返回值:
- css选择器匹配的Nodelist 对象集合
注意:
- 得到的是一个伪数组
- 有长度有索引的数组
- 但是没有pop() push()等数组方法
- 想要得到里面的每一个对象。则需要遍历(for)的方式获得
2-3.其他获得DOM元素的方法(了解) 
3.设置/修改DOM元素内容
3-1.document
- document.write()
- 只能将文本内容追加到前面的位置
- 文本包含的标签会被解析
3-2.对象.innerText属性
- 将文本内容添加/更新到任意 标签位置
- 文本中包含的标签不会被解析
3-3.对象.innerHTML属性
- 将文本内容添加/更新到任意标签位置
- 文本中包含的标签也会被解析
4.设置/修改DOM元素属性
4-1设置/修改元素常用属性
- 最常见的属性比如: href、title、src 等
4-2设置/修改元素样式属性
通过 style 属性操作CSS
操作类名(className) 操作CSS
通过 classList 操作类控制CSS
- 为了解决className 容易覆盖以前的类名,我们可以通过classList方式追加和删除类名
4-3设置/修改表单元素属性
-
表单很多情况,也需要修改属性,比如点击眼睛,可以看到密码,本质是把表单类型转换为文本框
-
正常的有属性有取值的 跟其他的标签属性没有任何区别
5.定时器-间歇函数
5-1开启定时器
- setInterval(函数,间隔时间)
5-2关闭定时器
6全选案例
<!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>
table {
width: 500px;
height: 300px;
margin: 100px auto;
text-align: center;
border-collapse: collapse;
}
thead {
height: 50px;
background-color: aquamarine;
}
</style>
</head>
<body>
<table border="1">
<thead>
<tr>
<th><input type="checkbox" class="checkAll">全选</th>
<th>商品名称</th>
<th>商家</th>
<th>商品价格</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
let arr = [
{name:'小米手机',business:'小米',price:'1999元'},
{name:'小米净化器',business:'小米',price:'4999元'},
{name:'小米电视',business:'小米',price:'5999元'},
]
let html = ``
let tbody = document.querySelector('tbody')
for (let index = 0; index < arr.length; index++) {
html +=`
<tr>
<td><input type="checkbox" class="ck"></td>
<td>${arr[index].name}</td>
<td>${arr[index].business}</td>
<td>${arr[index].price}</td>
</tr>
`
}
// console.log(html);
tbody.innerHTML = html
// 1 获取元素
let checkAll = document.querySelector('.checkAll')
let checkList = document.querySelectorAll('.ck')
// 2 设置全选点击事件
checkAll.addEventListener('click',function(){
let state = checkAll.checked
for (let index = 0; index < checkList.length; index++) {
checkList[index].checked = state
}
})
// 3 设置单选点击事件
for (let index = 0; index < checkList.length; index++) {
checkList[index].addEventListener('click',function(){
// 默认选中
let state = true
for (let index = 0; index < checkList.length; index++) {
// 如果有一个单选按钮未选中就设置全选按钮为未选中,且退出循环
if(checkList[index].checked==false){
state = false
break
}
}
// 设置全选按钮默认为选中状态
checkAll.checked = state
})
}
</script>
</body>
</html>
7.事件
事件是在编程时系统内发生的动作或者发生的事情
7-1事件监听
概念
- 就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 注册事件
语法:
事件监听三要素
-
事件源
- 那个dom元素被事件触发了,要获取dom元素
-
事件
- 用什么方式触发,比如鼠标单击click、鼠标经过mouseover等
-
事件调用的函数
- 要做什么事
7-2事件监听版本
- DOM L0 :是 DOM 的发展的第一个版本; L:level
- DOM L1:DOM级别1 于1998年10月1日成为W3C推荐标准,会覆盖事件
- DOM L2:使用addEventListener注册事件,重复绑定事件,不会覆盖
- DOM L3: DOM3级事件模块在DOM2级事件的基础上重新定义了这些事件,也添加了一些新事件类型
7-3事件类型
鼠标事件
- click 鼠标点击
- mouseenter 鼠标经过
- mouseleave 鼠标离开
- mouseover鼠标经过
- mouseout 鼠标离开
焦点事件
- focus 获得焦点
- blur 失去焦点
键盘事件
-
keydown 键盘按下触发
- keyup 键盘抬起触发
表单事件
- input 用户输入事件
8.高阶函数
8-1概念
- 高阶函数可以被简单理解为函数的高级应用,JavaScript 中函数可以被当成【值】来对待,基于这个特性实现函数的
8-2函数表达式
- 函数也是数据
- 把函数赋值给变量
8-3回调函数
- 把函数当做另外一个函数的参数传递,这个函数就叫做回调函数
- 回调函数本质还是函数,只不过把它当做成参数使用
- 使用匿名函数作为回调函数比较常见
9.环境对象
9-1.概念:
- 环境对象值的是函数内部特殊的变量this,它代表当前函数运行时所处的环境
9-2.作用:
-
弄清楚this的指向,可以让我代码更简洁
-
函数的调用方式不同,this只代的对象也不同
-
谁调用,this就是谁,是判断this指向的粗略规则
-
直接调用函数,其实相当于是window函数,所以this指代window
10.编程思想
10-1排他思想:
概念:
- 当前元素为A状态,其他元素为B状态
使用:
- 干掉所有人
- 使用for循环
- 复活他自己
- 通过this或者下标找到自己或者对用的元素
11.节点操作
11-1DOM节点
概念:
- DOM树里每一个内容都叫节点
分类:
- 元素节点
11-2查找节点
父节点查找
- parentNode属性
- 返回最近一级的父节点 找不到返回null
子节点查找
- childNodes
- 获得所有 子节点 包括文本节点(空格 换行)、注释节点等
- children (重点)
- 仅获得所有元素的节点
- 返回的还是一个伪数组
兄弟关系查找
-
下一个兄弟节点
- nextElementSibling
-
上一个兄弟节点
- previousElementSibling
11-3增加节点
创建节点
- 即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点
追加节点
- 要想在界面看到,还得插入到某个父元素中
- 插入到父元素的最后一个子元素:
- 插入到元素中的某个子元素的前面
克隆节点 
11-4删除节点
删除自己
12.时间对象
12.1获得当前时间
12.2获得指定时间
12.3属性
<script>
let span = document.querySelector('span')
setInterval(function(){
let time = new Date()
let year = time.getFullYear()
let month = time.getMonth()
let date = time.getDate()
let day = time.getDay()
let hour = time.getHours()
let minutes = time.getMinutes()
let seconds = time.getSeconds()
span.innerText = `现在是北京时间:${year}年${month+1}月${date}日 星期${day} ${hour}时${minutes}分${seconds}秒`
},1000)
</script>
12.4时间戳
-
是指1970年01月01日00时00分00秒起至现在的毫秒数,它是一种特殊的计量时间的方式
-
三种方式获取时间戳
1.使用getTime()方法
2.简写+new Date
13.微博发布案例
<!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>Document</title>
<link rel="stylesheet" href="css/weibo.css" />
</head>
<body>
<div class="w">
<div class="controls">
<img src="images/tip.png" alt="" /><br />
<textarea
placeholder="说点什么吧..."
id="area"
cols="30"
rows="100"
maxlength="200"
></textarea>
<div>
<span class="useCount">0</span>
<span>/</span>
<span>200</span>
<button id="send">发布</button>
</div>
</div>
<div class="contentList">
<ul>
<!-- <li>
<div class="info">
<img class="userpic" src="./images/9.5/06.jpg" />
<span class="username">张良</span>
<p class="send-time">发布于 2022-4-7 15:12:23</p>
</div>
<div class="content">sdfdf</div>
<span class="the_del">X</span>
</li> -->
</ul>
</div>
</div>
<script>
/*
1 给发布按钮绑定点击事件
1 生成一个li标签
1 给li添加属性和子元素
2 获取文本域的内容 设置到对应的标签中
2 插入到ul中
2 给文本域绑定 input事件
获取文字的长度 设置对应的标签上 文字个数标签上
3 给删除标签 绑定点击事件
1 获取它的父节点 parentNode
2 让它父节点 删除自己 remove()
*/
let dataArr = [
{ uname: '司马懿', imgSrc: './images/9.5/01.jpg' },
{ uname: '女娲', imgSrc: './images/9.5/02.jpg' },
{ uname: '百里守约', imgSrc: './images/9.5/03.jpg' },
{ uname: '亚瑟', imgSrc: './images/9.5/04.jpg' },
{ uname: '虞姬', imgSrc: './images/9.5/05.jpg' },
{ uname: '张良', imgSrc: './images/9.5/06.jpg' },
{ uname: '安其拉', imgSrc: './images/9.5/07.jpg' },
{ uname: '李白', imgSrc: './images/9.5/08.jpg' },
{ uname: '阿珂', imgSrc: './images/9.5/09.jpg' },
{ uname: '墨子', imgSrc: './images/9.5/10.jpg' },
{ uname: '鲁班', imgSrc: './images/9.5/11.jpg' },
{ uname: '嬴政', imgSrc: './images/9.5/12.jpg' },
{ uname: '孙膑', imgSrc: './images/9.5/13.jpg' },
{ uname: '周瑜', imgSrc: './images/9.5/14.jpg' },
{ uname: '老夫子', imgSrc: './images/9.5/15.jpg' },
{ uname: '狄仁杰', imgSrc: './images/9.5/16.jpg' },
{ uname: '扁鹊', imgSrc: './images/9.5/17.jpg' },
{ uname: '马可波罗', imgSrc: './images/9.5/18.jpg' },
{ uname: '露娜', imgSrc: './images/9.5/19.jpg' },
{ uname: '孙悟空', imgSrc: './images/9.5/20.jpg' },
{ uname: '黄忠', imgSrc: './images/9.5/21.jpg' },
{ uname: '百里玄策', imgSrc: './images/9.5/22.jpg' },
];
// 发布按钮
let send = document.querySelector('#send');
let area = document.querySelector('#area');
let ul = document.querySelector('ul');
let useCount = document.querySelector('.useCount');
// 点击
send.addEventListener('click', function () {
let user=getUser();
let liHtml = `
<li>
<div class="info">
<img class="userpic" src="${user.imgSrc}" />
<span class="username">${user.uname}</span>
<p class="send-time">发布于 ${getFormatTime()}</p>
</div>
<div class="content">${area.value}</div>
<span class="the_del">X</span>
</li
`;
// 每点击一次 在旧标签的基础上来 拼接多一个标签
ul.innerHTML += liHtml;
// 暂时没有办法解决的 实现 点击删除!! 事件委托技术 优雅解决
});
// area input事件
area.addEventListener('input', function () {
useCount.innerText = area.value.length;
});
// 函数 随机获取用户对象
function getUser() {
let index = Math.round(Math.random() * (dataArr.length - 1));
let user = dataArr[index];
return user;
}
// 获取有一定格式的时间
function getFormatTime() {
let nowDate = new Date();
let fullyear = nowDate.getFullYear();
let month = nowDate.getMonth();
let date = nowDate.getDate();
let hours = nowDate.getHours();
let minutes = nowDate.getMinutes();
let seconds = nowDate.getSeconds();
month = month < 10 ? '0' + month : month;
date = date < 10 ? '0' + date : date;
hours = hours < 10 ? '0' + hours : hours;
minutes = minutes < 10 ? '0' + minutes : minutes;
seconds = seconds < 10 ? '0' + seconds : seconds;
return `${fullyear}-${month}-${date} ${hours}:${minutes}:${seconds}`;
}
</script>
</body>
</html>
14.重绘和回流
- 重绘不一定引起回流,而回流一定会引起重绘
14.1回流
- 当 Render Tree 中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或全部文档的过程称为 回流
14.2重绘
- 由于节点(元素)的样式的改变并不影响它在文档流中的位置和文档布局时(比如:color、background-color、outline等), 称为重绘
14.3会导致回流(重绘)的操作
- 页面的首次刷新
- 浏览器的窗口大小发生改变
- 元素的大小或位置发生改变
- 改变字体的大小
- 内容的变化(如:input框的输入,图片的大小)
- 激活css伪类 (如::hover)
- 脚本操作DOM(添加或者删除可见的DOM元素)
- 简单理解影响到布局了,就会有回流
15.事件对象
15-1.获取事件对象:
概念
- 也是个对象,这个对象里有事件触发时的相关信息
获取
- 在事件绑定的回调函数的第一个参数就是事件对象,一般命名为event、ev、e
15-2.事件对象常用属性
属性
-
type
- 获取当前的事件类型
-
clientX/clientY
- 获取光标相对于浏览器可见窗口左上角的位置
-
offsetX/offsetY
- 获取光标相对当前DOM元素左上角的位置
-
key
-
用户按下的键盘键的值
-
现在不提倡使用keyCode
area.addEventListener('keydown', function (event) { // 判断按键是不是回车键 if (event.key === 'Enter') { // console.log("执行和按钮一样的功能"); // 给btn按钮绑定过点击事件,点击事件也是可以主动触发 btn.click(); // 你点击了一下按钮 // 解决按下回车 文本换行的效果 // 文本域的默认的行为 // 处理标签的默认行为 // return false event.preventDefault(); // 阻止浏览器标签的默认行为 阻止a标签默认跳转行为 } });
-
16.事件流
16-1.事件流与两个阶段说明
概念
- 事件流指的是事件完整执行过程中的流动路径
- 说明:假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段
- 简单来说:捕获阶段是 从父到子 冒泡阶段是从子到父
16-2.事件捕获和事件冒泡
事件捕获
- 父到子
- 参数true
事件冒泡
- 子到父
- 参数false(默认值)
16-3.阻止事件流动
阻止冒泡
- 此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
- 鼠标经过事件
- mouseover 和 mouseout 会有冒泡效果
- mouseenter 和 mouseleave 没有冒泡效果(推荐)
阻止默认行为
-
比如链接点击不跳转,表单域的不提交
区别
- 传统on注册
- 同一个对象,后面注册的事件会覆盖前面注册(同一个事件
- 直接使用null覆盖偶就可以实现事件的解绑
- 都是冒泡阶段执行的
- 事件监听注册
- 语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获
- 后面注册的事件不会覆盖前面注册的事件(同一个事件)
- 可以通过第三个参数去确定是在冒泡或者捕获阶段执行
- 必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
- 匿名函数无法被解绑
17.事件委托
17.1优点
- 给父级元素加事件(可以提高性能)
17.2原理
- 事件委托其实是利用事件冒泡的特点, 给父元素添加事件,子元素可以触发
17.3实现
- 事件对象.target 可以获得真正触发事件的元素
<script>
const ul = document.querySelector('ul');
ul.addEventListener('click', function (event) {
// event.target.style.backgroundColor="red";
// console.log(event.target);
// 只有点击了li标签才触发
// console.log(event.target.nodeName);// 当前点击的元素的标签名 大写
if (event.target.nodeName === 'LI') {
console.log('改变颜色');
event.target.style.backgroundColor = 'red';
}
});
</script>
18.学生信息案例
<script>
// 1.1 定义数组 负责存放表格要显示的数据
let arr = [ ];
const tbody = document.querySelector('tbody');
// 2 给 录入绑定点击事件
const add = document.querySelector('.add');
const uname = document.querySelector('.uname');
const age = document.querySelector('.age');
const gender = document.querySelector('.gender');
const salary = document.querySelector('.salary');
const city = document.querySelector('.city');
// 1.2 根据数组渲染页面
renderTableByArr();
// 2 按钮绑定点击事件
add.addEventListener('click', function () {
// 2.1 创建一个新的对象 把表单数据都合并到对象中
const data = {
// 学号
id: Date.now(),
// 姓名
uname: uname.value,
// 年龄
age: age.value,
// 性别
gender: gender.value,
// 薪资
salary: salary.value,
// 就业城市
city: city.value,
};
// 老师打了一个 断点 来验证 上面的代码 没有写错
// 2.2 给数组插入新的元素
arr.push(data);
// 2.3 数组发生改变 重新调用渲染页面的函数
renderTableByArr();
// 2.4 表单数据清空
uname.value = '';
age.value = '';
gender.value = '男';
salary.value = '';
city.value = '北京';
});
// 3 tbody绑定点击事件,同时判断被点击的是不是 del 删除标签
tbody.addEventListener('click', function (event) {
// 3.1 判断当前点击的是不是a标签
if (event.target.nodeName === 'A') {
// <a data-index="2" href="javascript:" class="del">删除</a>
// 获取到a标签 上存放的 index
// event.target = a标签的dom元素
// console.dir(event.target.dataset.index)
const index = event.target.dataset.index;
// 3.3 执行数组删除元素
arr.splice(index,1);
// 3.4 调用根据数组渲染页面的函数
renderTableByArr();
}
});
// 根据数组渲染表格
function renderTableByArr() {
let html = ``;
for (let index = 0; index < arr.length; index++) {
html += `
<tr>
<td>${arr[index].id}</td>
<td>${arr[index].uname}</td>
<td>${arr[index].age}</td>
<td>${arr[index].gender}</td>
<td>${arr[index].salary}</td>
<td>${arr[index].city}</td>
<td>
<a data-index="${index}" href="javascript:" class="del">删除</a>
</td>
</tr>
`;
}
// 把生成的tr插入到 tbody中
tbody.innerHTML = html;
}
</script>
19.滚动事件和加载事件
19.1滚动事件
应用
- 很多网页需要检测用户把页面滚动到某个区域后做一些处理, 比如固定导航栏,比如返回顶部
语法
- 给window或document添加scroll事件
固定导航栏
let nav = document.querySelector('nav')
let header = document.querySelector('header')
window.addEventListener('scroll',function(){
let scrollTop = document.documentElement.scrollTop
if(scrollTop>=100) {
nav.classList.add('fixed')
header.style.marginBottom = 100 + 'px';
}else{
nav.classList.remove('fixed')
header.style.marginBottom = 0;
}
})
19.2加载事件
事件名load
- 监听页面所有资源加载完毕
- 给 window 添加 load 事件
事件名DOMContentLoaded
- 当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像等完全加载
- 监听页面DOM加载完毕
- 给 document 添加 DOMContentLoaded 事件
20.元素大小的位置
20.1scroll家族
获取宽高
- 获取元素的内容总宽高(不包含滚动条)返回值不带单位
- scrollWidth和scrollHeight
/*
scrollWidth 不包含滚动条的大小
scrollHeight 等于容器可以滚动的大小 滚动条的大小的大小为17px
*/
let scrollDom = document.querySelector('div')
// 输出它宽高
console.log(scrollDom.scrollHeight);
console.log(scrollDom.scrollWidth);
获取位置
- 获取元素内容往左、往上滚出去看不到的距离
- scrollLeft和scrollTop
- 这两个属性是可以修改的
// 获取当前容器滚动了的距离scrollDom.addEventListener('scroll',function(){
console.log(this.scrollLeft);
console.log(this.scrollTop);
})
总结
/*
1 页面滚动 使用 window.addEventListenner("scroll")事件
2 页面的滚动距离 document.documentElement.scrollTop
1 元素滚动 dom.addEventListenner("scroll")
2 获取元素滚动的距离
dom.scrollTop
dom.scrollLeft
3 scrollWidth 整个可以滚动的区间的宽度
4 scrollHieght 整个可以滚动的区域的高度
小细节 pc端的滚动条的大小17px 移动端的滚动条不占大小
*/
20.2offset家族
获取宽高
- 获取元素的自身宽高、包含元素自身设置的宽高、padding、border
- offsetWidth和offsetHeight
let offsetDom = document.querySelector('.offset')
// // 获取宽度和高度 包含这滚动条的大小
console.log(offsetDom.offsetWidth);
console.log(offsetDom.offsetHeight);
获取位置
- 获取元素距离自己定位父级元素的左、上距离
- offsetLeft和offsetTop注意是只读属性
// 获取当前元素距离 定位了的父元素的大小(找不到定位了的父元素,相对于页面来计算)
console.log(offsetDom.offsetTop);
console.log(offsetDom.offsetLeft);
总结
/*
总结 offset家族
1 offsetWidth 获取元素的宽度 包含这滚动条
2 offsetHeight 获取元素的高度 包含这滚动条
3 offsetLeft 获取定位了的父元素的 水平距离 左
4 offsetTop 获取定位了的父元素的 垂直距离 上
*/
20.3client家族
获取宽高
- 获取元素的可见部分宽高(不包含边框,滚动条等)
- clientWidth和clientHeight
let clientDom = document.querySelector('.client')
// 宽度和高度
console.log(clientDom.clientWidth); // 不包含 滚动条(类似 scrollWidth)
console.log(clientDom.clientHeight); // 不包含 滚动条(类似 scrollHeight)
获取位置
- 获取左边框和上边框宽度
- clientLeft和clientTop 注意是只读属性
// 获取边框的大小
console.log(clientDom.clientLeft); // 左边框
console.log(clientDom.clientRight); // 有没有?
console.log(clientDom.clientTop); // 上边框
20.4区别
// 区别
// scollWidth 获取容器的宽度(包含滚动的区域)
// offsetWidth 获取可视区域的宽度(包含滚动条)
// clientWidth 获取可视区域的宽度(不包含滚动条)
// scrollLeft 获取左侧滚动的距离
// offsetLeft 获取和已经定位了的父级元素的左距离
// clientLeft 获取左边框的大小
20.5屏幕大小改变事件
<script>
// let title = document.querySelector('title')
// 页面大小发生变化了就会触发的事件 resize window来绑定
window.addEventListener('resize', function (event) {
console.log('页面大小发生变化了');
// 移动端屏幕适配 rem 淘宝js库,flexible.js 作用 设置html的字体大小 为当前页面的宽度的十分之一
// 获取当前页面的宽度
console.log(document.body.offsetWidth);
// 设置页面html标签的字体大小为屏幕的十分之一
document.documentElement.style.fontSize =
document.body.offsetWidth / 10 + 'px';
// 响应式布局的时候 发一个js文件 方便根据当前页面的宽度 告诉我们屏幕的种类和宽度
const width = document.body.offsetWidth;
if (width > 1200) {
document.querySelector('title').innerText = `大屏幕 ${width}`;
} else if (width > 992) {
document.querySelector('title').innerText = `中等屏幕 ${width}`;
} else if (width > 768) {
document.querySelector('title').innerText = `小屏幕 ${width}`;
} else {
document.querySelector('title').innerText = `极小屏幕 ${width}`;
}
});
21.购物车综合案例
<script>
// 购物车-实现步骤
// 获取元素
let carBody = document.querySelector('#carBody')
let totalCountEle = document.querySelector('#totalCount')
let totalPriceEle = document.querySelector('#totalPrice')
// 1 动态渲染
function init(){
let htmlStr = ''
// 遍历数据
data.forEach(function(value,index){
// console.log(123);
htmlStr += `
<tr>
<td>
<input class="s_ck" type="checkbox" ${value.state ? 'checked' : ''}/>
</td>
<td>
<img src="${value.img}" />
<p>${value.name}</p>
</td>
<td class="price">${value.price}</td>
<td>
<div class="count-c clearfix">
<button class="reduce" data-index = "${index}" ${value.count==1? 'disabled' : ''}>-</button>
<input type="text" value="${value.count}" />
<button class="add" data-index="${index}">+</button>
</div>
</td>
<td class="total">${value.price*value.count}¥</td>
<td>
<a href="javascript:" class="del" >删除</a>
</td>
</tr>
`
})
carBody.innerHTML = htmlStr
}
init()
// 2 计算出总数和总价格
function computerTotal(){
let totalCount = 0
let totalPrice = 0
data.forEach(function(value,index){
if(value.state){
totalCount++
totalPrice+=value.price*value.count
}
})
totalCountEle.innerHTML = totalCount
totalPriceEle.innerHTML = totalPrice
}
computerTotal()
// 3 数量增减
carBody.addEventListener('click',function(e){
if(e.target.className=='add'){
// console.log(123);
let index = e.target.dataset.index;
data[index].count++
// 重新渲染
init()
// 重新计算
computerTotal()
}else if(e.target.className=='reduce'){
let index = e.target.dataset.index
data[index].count--
// 重新渲染
init()
// 重新计算
computerTotal()
}
})
// 4 全选
// 5 列表中的选中
// 6 删除所选商品
// 7 清理购物车
// 8 数据删除
</script>
22.轮播图综合案例
<!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;
}
.big {
width: 815px;
}
</style>
</head>
<body>
<h1>美女画廊</h1>
<div>
</div>
<img class="big" src="./placeholder.png" alt="">
<h3>选择图片</h3>
<script>
let div = document.querySelector('div')
let big = document.querySelector('.big')
let h3 = document.querySelector('h3')
let index = 0
// 1 定义数组
let arr = [
{small:"./1-small.jpg",big:"./1.jpg",title:"美女A"},
{small:"./2-small.jpg",big:"./2.jpg",title:"美女B"},
{small:"./3-small.jpg",big:"./3.jpg",title:"美女C"},
{small:"./4-small.jpg",big:"./4.jpg",title:"美女D"}
]
// 2 写一个函数负责渲染小图片
function render(){
let imgHtml = ''
for (let index = 0; index < arr.length; index++) {
imgHtml+= `<img src="./${index+1}-small.jpg" alt="">`
}
div.innerHTML = imgHtml
}
// 调用渲染小图片
render()
// 3 遍历小图片 绑定点击事件
let imgSmall = document.querySelectorAll('div img')
for (let index = 0; index < imgSmall.length; index++) {
imgSmall[index].addEventListener('click',function(){
// console.log(123);
renderByindex(index)
})
}
// 根据下标来显示对应的内容
function renderByindex(arrIndex){
big.src = arr[arrIndex].big
h3.innerHTML = arr[arrIndex].title
}
</script>
</body>
</html>
23.window对象
23.1 BOM(浏览器对象模型)
- BOM(Browser Object Model ) 是浏览器对象模型
- window 是浏览器内置中的全局对象,我们所学习的所有 Web APIs 的知识内容都是基于 window 对象实现的
- window 对象下包含了 navigator、location、document、history、screen 5个属性,即所谓的 BOM (浏览器对象模型)
- document 是实现 DOM 的基础,它其实是依附于 window 的属性
23.2 定时器-延时函数
- JavaScript 内置的一个用来让代码延迟执行的函数,叫 setTimeout
- setTimeout 仅仅只执行一次,所以可以理解为就是把一段代码延迟执行, 平时省略window
- 清除延时函数
定时器
23.3 JS执行机制
23.4 location对象
属性
- href 属性获取完整的 URL 地址,对其赋值时用于地址的跳转
- search 属性获取地址中携带的参数,符号 ?后面部分
- hash 属性获取地址中的啥希值,符号 # 后面部分
- reload 方法用来刷新当前页面,传入参数 true 时表示强制刷新
23.5 navigator对象
- 主要用来获取浏览器的信息
属性
- 通过 userAgent 检测浏览器的版本及平台
23.6 histroy对象
history 的数据类型是对象,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
属性
<body>
<a href="http://www.baidu.com">百度</a>
<button class="forward">前进</button>
<button class="back">后退</button>
<script>
const forward = document.querySelector('.forward');
forward.addEventListener('click', function () {
// history.forward();
history.go(1); // 前进一个记录
});
const back = document.querySelector('.back');
back.addEventListener('click', function () {
// history.back();
history.go(-1); // 后退一个记录
});
</script>
</body>
23.7递归
概念
- 一个函数调用自己
使用场景
-
1 有一个函数,可以打印出 一个dom元素的所有祖先元素
- 不可能提前知道 这个a标签有多少个父元素
- 这个函数接收一个参数,= dom
- 如果这个dom元素有父元素,就继续调用自己函数
-
2 假设你现在得了肺炎 警察叔叔
- 先找你 -> 找你的邻居(得了肺炎) -> 找你的邻居的邻居(得了肺炎)->找你的邻居的邻居(得了肺炎)... 直到找到一个邻居 没事 警察叔叔 不找结束了
const button = document.querySelector('button'); getParent(button); function getParent(dom) { console.log(dom); if (dom.parentNode) { // 如果有父元素 getParent(dom.parentNode); } else { console.log('结束啦'); } }// 定时器 不主动清除,定时器永远执行下去 // 延时器 只会执行一次 // 延时器实现定时器的功能 // 在延时器 又开启一个延时器, // 递归 自己调用自己 函数自己调用自己 let index=0; function func() { console.log(++index); setTimeout(func,1000); }; func();
23.8屏幕大小改变事件
// 页面大小发生变化了就会触发的事件 resize window来绑定
window.addEventListener('resize', function (event) {
console.log('页面大小发生变化了');
// 移动端屏幕适配 rem 淘宝js库,flexible.js 作用 设置html的字体大小 为当前页面的宽度的十分之一
// 获取当前页面的宽度
console.log(document.body.offsetWidth);
// 设置页面html标签的字体大小为屏幕的十分之一
document.documentElement.style.fontSize =
document.body.offsetWidth / 10 + 'px';
// 响应式布局的时候 发一个js文件 方便根据当前页面的宽度 告诉我们屏幕的种类和宽度
const width = document.body.offsetWidth;
if (width > 1200) {
document.querySelector('title').innerText = `大屏幕 ${width}`;
} else if (width > 992) {
document.querySelector('title').innerText = `中等屏幕 ${width}`;
} else if (width > 768) {
document.querySelector('title').innerText = `小屏幕 ${width}`;
} else {
document.querySelector('title').innerText = `极小屏幕 ${width}`;
}
});
24.swiper插件
- 插件: 就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果
- 熟悉官网,了解这个插件可以完成什么需求 www.swiper.com.cn/
- 看在线演示,找到符合自己需求的demo www.swiper.com.cn/demo/index.…
- 查看基本使用流程 www.swiper.com.cn/usage/index…
- 查看APi文档,去配置自己的插件 www.swiper.com.cn/api/index.h…
- 注意: 多个swiper同时使用的时候, 类名需要注意区分
25.补充
25-1.console.log和console.dir区别
/*
区别在于
有时候 我们使用console.log 打印dom元素的时候 输出一个标签格式 而不是一个对象格式
console.dir 输出dom元素的元素 总是 对象格式
*/
const btn=document.querySelector("button");
// console.log(btn);
console.dir(btn);
25-2.区分属性和方法
// 属性的获取和使用 不需要加括号
// 方法加括号
// document.body.style.display="none"// 属性
// document.body.classList.add()// 方法
// 利用编辑器 只要你不是色盲 你知道怎么区分
// document.body.style.display
// document.body.classList.a
25-3.页面换肤功能
<!-- 在网页中 提供一个标签 让用户选择颜色 -->
<!-- color标签有兼容性问题 少用 了解 -->
<input type="color" />
<script>
const colorInput = document.querySelector('input');
// 需要给这个标签 绑定 change事件 - 选好了值之后,就会触发的一个事件
colorInput.addEventListener('change', function () {
// 通过 value属性来获取 选中的颜色
// console.log(this.value);
// 设置到body标签中即可
document.body.style.backgroundColor = this.value;
});
26.本地存储
26-1特性
- 数据存储在用户浏览器中
- 设置、读取方便、甚至页面刷新不丢失数据
- 容量较大,sessionStorage和localStorage约 5M 左右
26-2localStorage
1 概念
- 生命周期永久生效,除非手动删除 否则关闭页面也会存在
- 可以多窗口(页面)共享(同一浏览器可以共享)
- 以键值对的形式存储使用
2 存储数据
- localStorage.setItem(key, value)
3 获取数据
- localStorage.getItem(key)
4 删除数据
- localStorage.removeItem(key) 删除一个
- localStorage.clear(); 删除所有
5 存储复杂数据类型存储
- 本地只能存储字符串,无法存储复杂数据类型.需要将复杂数据类型转换成JSON字符串,在存储到本地
- JSON.stringify(复杂数据类型)
- 将复杂数据转换成JSON字符串 存储 本地存储中
- JSON.parse(JSON字符串)
- 将JSON字符串转换成对象 取出 时候使用
26-3sessionStorage
概念
- 本地存储的技术 sessionStorage 会话(打开页面到关闭页面之间过程 一次会话 ajax node)存储
- 它的用法和 localStorage 用法一样
- 区别只有一个
- sessionStorage 关闭页面后 数据就丢失
- localStorage 除非是用户主动删除 否则一直存在 直到天荒地老
使用
// 存数据
// sessionStorage.setItem("ss",123);
// 取数据
// console.log(sessionStorage.getItem("ss"));
// 删除一个
// sessionStorage.removeItem("ss")
// 清空
// sessionStorage.clear();
27.元素属性
27-1固有属性
- 标签天生自带的属性 比如class id title等, 可以直接使用点语法操作
// 获取 dom元素的固有属性 通过点语法来获取
const a = document.querySelector('a');
// 获取固有属性
// console.log(a.href);
// console.log(a.id);
// 直接修改
// a.href="http://www.qq.com";
// a.id="top";
27-2自定义属性
- 由程序员自己添加的属性,在DOM对象中找不到, 无法使用点语法操作,必须使用专门的API
- getAttribute('属性名') // 获取自定义属性
- setAttribute('属性名', '属性值') // 设置自定义属性
- removeAttribute('属性名') // 删除自定义属性
// 自定义属性 不能直接通过点语法来获取和设置
// 获取 getAttribute("属性名")
// console.log(a.hello);
// console.log(a.aa);
// console.log( a.getAttribute("hello") );
// console.log( a.getAttribute("aa") );
// 设置 setAttribute(key,value)
// a.setAttribute("hello","123");
// 删除掉属性 removeAttribute(key)
// a.removeAttribute("hello");
// 自定义属性 -> h5建议的 自定义属性
// 属性的时候 data-xxx 开头
// 获取的时候 a.dataset.xxx
// 设置 a.dataset.index = 3;
// console.log(a.dataset.index);
// a.dataset.index = 3;
27-3总结
/*
小结
标签的属性 有两种分为
1 固有属性 比如 id href src 点语法的方式获取和设置 方便
2 自定义属性
1 随机自己瞎命名
<a abc="123" >
获取 (getAttribute) 设置 setAttribute(key,value) 删除 removeAttribute(key)
2 h5建议 data- xxx
<a data-abc="123" >
获取(a.dataset.abc) 设置(a.dataset.abc=456);
3 最强大是 (getAttribute) setAttribute removeAttribute
上述的这个方式,可以获取到任意的属性(固有属性和h5建议的自定义属性)
<a data-index="0" id="nav" href="http://www.baidu.com" hello="no" aa="bb" >跳转</a >
*/
28.事件绑定和取消绑定
<script>
// const btn = document.querySelector('button');
// // 普通函数
// function func() {
// console.log('2022-04-15 14:32:26');
// }
// function func2() {
// console.log("func2");
// }
// // 绑定事件
// btn.addEventListener('click', func);
// // addEventListener 可以绑定多个同名事件
// btn.addEventListener('click', func2);
// setTimeout(function () {
// // 取消这个事件绑定
// btn.removeEventListener('click', func);
// }, 5000);
/*
1 addEventListener 可以绑定多个同名事件
2 removeEventListener 可以取消对应的事件类型和事件处理函数
3 无法取消 addEventListener 事件 对应的匿名函数
*/
const btn=document.querySelector("button");
btn.addEventListener("click",function () {
console.log("你好");
})
// 想要取消 这个 输出你好的行为
btn.removeEventListener("click",???);
</script>
29.事件流动
<body>
<div class="a">爷爷
<div class="b">爸爸
<div class="c">儿子</div>
</div>
</div>
<script>
/*
事件流动 3个阶段
1 最重要的冒泡阶段
2 知道 捕获阶段
addEventListener 第三个参数 true|false 来进行切换
3 目标阶段 了解一下
*/
const a=document.querySelector(".a");
const b=document.querySelector(".b");
const c=document.querySelector(".c");
a.addEventListener("click",function () {
console.log("爷爷");
})
b.addEventListener("click",function () {
// 这个c 是最底层的元素
console.log("爸爸");
})
c.addEventListener("click",function () {
// 这个c 是最底层的元素
console.log("儿子 目标阶段");
})
</script>
</body>
30.字符串方法
<script>
// 我们在实际开发过程中,有很多需求要针对字符串做处理
// js 帮我们封装了很多大量和实用 字符串方法
// 先介绍一些
// 转大写 转小写。
// let msg = 'HELLODFDFDFDFDFD';
// 广告 msg 大写
// msg="HELLO";// 搞定 楼下大妈也会!!! low 低级 不堪入目
// console.log(msg.toUpperCase());
// 转小写
// console.log(msg.toLowerCase()); //转成小写
// 字符串和数组很相似
// 能不能把字符串 转成数组?
const str="abcdefg"; //=> ["a","b","c","d","e","f","g"]
// // split("") 分割
// console.log(str.split(""));
// const str = 'a-b-c-d-e-f-g'; // ["a","b","c","d","e","f","g"]
// console.log(str.split('-'));
// console.dir(str);
/*
1 转大写 toUpperCase()
2 转小写 toLowerCase()
3 转数组 str.split('') 按照什么来分割你的字符串变成数组
*/
</script>
30-1数组方法
// 数组 补充 常用
//
// const arr = ['a', 'b', 'c', 'd'];
// console.log(arr.join('')); // join 数组转字符串
// console.log(arr.join('-')); // a-b-c-d 数组转字符串
// 连接 数组和数组之间连接
// const arr1 = ['1', '2', '3'];
// const arr2 = ['a', 'b', 'c'];
// 将两个数组合并成一个数组
// console.log(arr1.concat(arr2));
//字符串也有一个 concat 也是表示合并
const str1 = '123';
const str2 = 'abc';
// console.log(str1.concat(str2));// 很少用 有什么用? 当你的键盘 + 键坏 使用它
console.log(str1 + str2); // 更加简单好理解
</script>
31.正则表达式
31.1概念
- 正则表达式(Regular Expression)是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象
- 通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式
31.2作用
- 表单验证(匹配)
- 过滤敏感词(替换)
- 字符串中提取我们想要的部分(提取)
31.3语法
test() 方法
-
用来查看正则表达式与指定的字符串是否匹配
-
定义正则表达式
-
检索查找是否匹配
exec() 方法
-
在一个指定字符串中执行一个搜索匹配
-
定义正则表达式
-
如果匹配成功,exec() 方法返回一个数组,否则返回null
31.4元字符
普通字符
元字符(特殊字符)
边界符
- 表示位置,开头和结尾,必须用什么开头,用什么结尾
- 如果 ^ 和 $ 在一起,表示必须是精确匹配。
const str = `俊朗的外表,美丽的弧线,明星的妻子,自豪的荣誉,青春的记忆,梦幻的传奇,无尽的伤病,世人的指摘,自我的救赎,上帝的眷顾,这就是大卫贝克汉姆`
// 定义规则 ^ 以什么开头
// const reg = /^俊朗/ //以俊朗开头的
// console.log(reg.test(str)); //返回true
// 定义规则 $ 以什么结尾
const reg = /贝克汉姆$/ //以贝克汉姆结尾的
console.log(reg.test(str)); //返回true
量词
字符类
- . 表示除了(换行符之外)任意字符
- \d 表示数字
- \D 不是数字之外的任意1个字符
- \w 字母、数字、下划线
- \W 除去了 字母 、数字、下划线 之外字符
- \s 匹配空格
- \S 除了空格之外的字符
- [a-z] 表示 a 到 z 26个英文字母都可以
- [A-Z] 表示字母大写都可以
- [0-9] 表示 0~9 的数字都可以
- [0-9a-zA-Z] 表示数字0-9 字母a-z大小写
31.5修饰符
- 修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等
语法
替换 replace 替换