JS简介
JavaScript是一种运行在浏览器的编程语言,实现人机交互效果。可以做网页特效、表单验证、数据交互、服务端编程。
ECMAScript规定了JavaScript的基础语法,如变量、分支语句
Web APIs分为:DOM操作文档,如对页面元素进行添加删除等;BOM操作浏览器,如页面弹窗等
js书写位置
内部js
直接写作html文件里,用script标签包住,script标签写在</body>上面
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
// 页面弹出警示框
alert('你好,js!')
</script>
</body>
</html>

外部js
代码写在以.js结尾的文件里,通过script标签引入到html页面中
新建一个js文件夹,创建一个.js文件

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script src="./js/my.js"></script>
</body>
</html>

此时<script>标签中间无需写内容(写了也会被忽略)
内联js
代码写在标签内部
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<button onclick="alert('我是内联js')">点击</button>
</body>
</html>

js的结束符使用英文的";",在实际开发中可写可不写,浏览器可自动推断出语句的结束位置
输出语法
向body输出内容。如果输出的内容写的是标签,也会被解析成网页元素
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
// 向文档输出内容
ducument.write('你好')
document.write('<h1>我是一级标题</h1>')
// 页面弹出警告对话框
alert('欢迎')
// 控制台打印输出
console.log('给程序员看')
</script>
</body>
</html>


输入语法
显示一个对话框,对话框中包含一条文字信息
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
prompt('请输入您的姓名:')
</script>
</body>
</html>

JS代码执行顺序
按HTML文档流顺序执行
alert()和promt()会跳过页面渲染先被执行
变量
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
// 声明变量
let age
// 变量赋值
age = 18
// 变量初始化
let name = 'js'
alert(age)
document.write(name)
</script>
</body>
</html>

案例
浏览器中弹出对话框,输入姓名,页面中输出刚刚输入的姓名
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
let uname = prompt('请输入姓名')
document.write(uname)
</script>
</body>
</html>

数组
一种将一组数据存储在单个变量名下的方式,数组索引从0开
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
// 声明数组
let arr = [10, 20, 30]
document.write(arr[1])
document.write(' ' + arr.length)
</script>
</body>
</html>

常量
使用const声明的变量称为"变量",在声明时必须赋值,不允许重复赋值
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
const PI = 3.14
document.write(PI)
</script>
</body>
</html>

数据类型
js是弱数据类型的语言,只有赋值后才知道是什么数据类型
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
// 数字类型
let num = 10.11
document.write(num + 1)
// 字符串类型
let name = 'JavaScript'
document.write(' 我的名字叫:' + name)
// 布尔类型
let flag = true
document.write(' ' + 3 > 4)
//未定义类型
let n
document.write(' ' + n)
// 空类型
let obj = null
document.write(' ' + obj)
</script>
</body>
</html>

可以发现多个空格也只有一个
模板字符串
用于拼接字符串和变量,使用"`"键盘1左边的反引号,用${}包住变量
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
let age = 18
document.write(`我今年${age}岁了`)
</script>
</body>
</html>

检测数据类型
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
let num = 10
document.write(typeof num)
let str = '你好'
document.write(typeof (str))
</script>
</body>
</html>

类型转换
js中使用prompt和表单获取过来的数据默认为字符串类型,此时就不能直接简单进行计算
隐式转换
某些运算符被执行时,系统内部自动将数据类型进行转换
如+号两边只要有一个是字符串,都会把另外一个转为字符串;除了+以外的算术运算符都会把数据转成数字类型;+作为正号解析可以转换成数字型
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
console.log('你好' + 1)
console.log(2 + '2') // 22
console.log(2 - '2') // 0
console.log(+12)
console.log(+'123') // 可转换为数字型
console.log(typeof +'123')
</script>
</body>
</html>

显示转换
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
let str = '123'
// 转换为数字类型
console.log(Number(str))
let num = +prompt('输入年龄')
console.log(num)
// 只保留整数
console.log(parseInt('12px'))
console.log(parseInt('12.64px'))
console.log(parseInt('abc12.64px'))
// 可以保留小数
console.log(parseFloat('12.34px'))
</script>
</body>
</html>

运算符
赋值运算符:=、+=、-=...
一元运算符:++、--、!
比较运算符:>、==、===(左右两边是否类型和值都相等)、>=...
逻辑运算符:&&、||、!
语句
表达式 是可以被求值的代码,语句是一段可以执行的代码
分支语句
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
// 单分支if语句
if (true) {
console.log('执行语句')
}
if (2) {
console.log('数字除了0都为真')
}
if ('你好') {
console.log('字符串除了空字符都为真')
}
if (2 > 1) console.log('2>1')
// 双分支if语句
let uname = 'eat'
if (uname === 'eat') {
console.log('登陆成功')
} else {
console.log('登陆失败')
}
// 多分支if语句
if (false) {
console.log(false)
} else if (2) {
console.log('2')
} else {
console.log(null)
}
// 三元运算符
console.log(3 > 5 ? 3 : 5)
// sitch语句
switch ('周一') {
case '周一':
console.log('今天是周一')
break
case '周二': break
default: break
}
</script>
</body>
</html>

循环语句
while循环
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
let i = 1
while (i <= 3) {
document.write('我会循环3次<br>')
i++
}
let n = 1
while (n <= 5) {
if (n == 4) {
break
}
document.write('我也会循环3次<br>')
n++
}
let num = 1
while (num <= 3) {
num++
if (num == 2) {
continue
}
document.write('我会循环2次<br>')
}
</script>
</body>
</html>

for循环
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
for (let i = 1; i <= 3; i++) {
document.write('我会输出3次<br>')
}
</script>
</body>
</html>
断点演示
先编写代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
let num = 10
num++
console.log(num)
</script>
</body>
</html>
右键浏览器,点击"源代码"

双击左侧的页面文件

在第14行左侧点击,打断点

然后刷新页面,可以看到底下显示断点处num为11,并且变量名旁也会显示值

数组
数组是一种可以按顺序保存数据的数据类型
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
// 字面量声明数组
let arr = [1, 2, '你好', true] // 数组中的数据类型不必相同
// 使用new Array构造函数声明
let arr1 = new Array(1, 2, '你好')
// 通过下标获取数据
document.write(arr1[2] + '<br>')
document.write(arr)
// 修改数组里的内容
arr[3] = 'js'
document.write('<br>' + arr)
// push方法将一个或多个元素添加到数组末尾,并返回该数组的长度
arr.push(true)
document.write('<br>' + arr)
document.write('<br>' + arr.push(true))
// unshift方法将一个或多个元素添加到数组的开头,并返回该数组的长度
arr.unshift(11.5)
document.write('<br>' + arr)
// pop方法从数组中删除最后一个元素,并返回该元素的值
arr.pop()
document.write('<br>' + arr)
// splice(起始位置,删除几个元素)方法删除指定元素
arr.splice(0, 1)
document.write('<br>' + arr)
</script>
</body>
</html>

函数
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
function sheet() {
for (let i = 1; i <= 9; i++) {
for (let j = 1; j <= i; j++) {
document.write(`${j}X${i}=${j * i} `)
}
document.write('<br>')
}
}
// 调用
sheet()
</script>
</body>
</html>

函数传参
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
function getSum(num1 = 0, num2 = 0) {
document.write(num1 + num2 + '<br>')
}
getSum(1, 2)
function getArrSun(arr = []) {
let sum = 0
for (let i = 0; i < arr.length; i++) {
sum += arr[i]
}
document.write(sum)
}
getArrSun([1, 2, 3, 4, 5])
</script>
</body>
</html>

函数返回值
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
function fn() {
return 20
}
document.write(fn())
</script>
</body>
</html>

匿名函数
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
// 1.函数表达式,将匿名函数赋值给一个变量,通过变量名进行调用
// 函数表达式必须先声明后调用(具名函数的调用可以写在任意位置)
let fn = function () {
document.write('我是函数表达式')
}
fn();
// 2.立即执行函数
(function () {
document.write('<br>不用调用就执行')
})();
//立即执行函数必须加分号,第二个小括号是调用函数
(function (x, y) {
document.write('<br>' + (x + y))
})(1, 2);
</script>
</body>
</html>

对象
对象是JavaScript里的一种数据类型,用来描述某个事物,无序
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
// 声明对象
let teacher = {
// 多个属性用,隔开
uname: '老师',
age: 20,
gender: '女',
'scholl-name': 'zjs',
// 方法(匿名函数)
sayHi: function () {
console.log('Hi')
}
}
console.log(teacher)
console.log(typeof teacher)
// 查询属性值
console.log(teacher.age)
console.log(teacher['school-name'])
// 修改属性值
teacher.age = 28
// 新增属性
teacher.hobby = '篮球'
// 调用方法
teacher.sayHi()
// 遍历对象
for (let key in teacher) {
console.log(key)
console.log(teacher[key])
}
</script>
</body>
</html>

遍历数组对象
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
let students = [
{ name: '小明', age: 18, gender: '男' },
{ name: '小洪', age: 19, gender: '女' },
{ name: '小刚', age: 18, gender: '男' },
]
for (let i = 0; i < students.length; i++) {
console.log(students[i].name)
}
</script>
</body>
</html>

变量声明
变量声明const优先
const声明的值不能更改,但是对于引用数据类型,const声明的变量里面存的是地址,不是值
以下情况正确
html
// 对象
const person = {
uname: '小明',
age: 18,
gender: '男'
}
person.age = 20
person.hobby = '篮球'
const names=[]
names[0]=1
names[1]=2
const obj={}
obj.name='老师'
下面情况错误
html
// 错误,地址不一样
const names = []
names = [1, 2, 3]
const obj = {}
obj = { uname: '老师' }
Web APIs
简介
作用:使用JS去操作html和浏览器
分类:DOM(文档对象模型,提供一套操作网页/标签内容的工具)、BOM(浏览器对象模型)
DOM对象
浏览器根据html标签生成的JS对象,所有标签属性都可以在这个对象上面找到,修改这个对象的属性会自动映射到标签身上
核心就是把网页内容当作对象来处理
网页所有的内容都在document对象里面
获取DOM对象
根据CSS选择器获取DOM元素,document.querySelector('css选择器')
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<div class="box"></div>
<p id="nav">123</p>
<ul>
<li></li>
<li></li>
</ul>
<script>
// 获取匹配的第一个元素
const div = document.querySelector('div')
console.log(div)
const box = document.querySelector('.box')
console.log(box)
const nav = document.querySelector('#nav')
console.log(nav)
// 获取第一个小li
const li = document.querySelector('ul li')
console.log(li)
// 选择匹配的多个元素,返回匹配的NodeList对象集合
const lis = document.querySelectorAll('ul li')
console.log(lis)
// 修改
nav.style.color = 'red'
</script>
</body>
</html>

操作元素内容
innerText属性用于将文本内容添加/更新到任意标签位置,显示纯文本,不解析标签
innerHTML属性也可以将文本内容添加/更新到任意标签位置,但可以解析标签(多标签建议使用模板字符)
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<div class="box">内容</div>
<div class="box1">内容</div>
<script>
const box = document.querySelector('.box')
const box1 = document.querySelector('.box1')
// 修改文字内容使用 对象.innerText
box.innerText = '<br>我是一个盒子'
// 使用.innerHTML
box1.innerHTML = '<br>我是一个盒子'
</script>
</body>
</html>

操作元素属性
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<img src="spring.jpg" alt="">
<script>
// 获取图片元素
const img = document.querySelector('img')
// 修改属性
img.src = 'summer.jpeg'
img.title = '夏天'
</script>
</body>
</html>
操作元素样式属性
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
<style>
.box {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
const box = document.querySelector('.box')
// .style.样式属性 = '值'
box.style.width = '300px'
// 多组单词彩玉小驼峰命名法
box.style.backgroundColor = 'black'
</script>
</body>
</html>

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
<style>
.nav {
color: red;
}
.box {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div class="nav">123</div>
<script>
const div = document.querySelector('div')
// 使用新属性换旧属性(也可做添加属性)
div.className = 'box'
</script>
</body>
</html>

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
<style>
.nav {
color: red;
}
.box {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div class="nav">123</div>
<script>
const div = document.querySelector('div')
// 添加类名
div.className = 'nav box'
</script>
</body>
</html>

最常用的是通过classList操作类控制CSS
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
<style>
.nav {
color: red;
}
.box {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div class="nav">123</div>
<script>
const div = document.querySelector('div')
// 追加类名
div.classList.add('box')
// 删除类
div.classList.remove('nav')
// 切换类(有则删除,没有则添加)
div.classList.toggle('box')
</script>
</body>
</html>

操作表单元素属性
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<input type="text">
<br>
<input type="checkbox" name="" id="">
<script>
const text = document.querySelector('input')
// 获取表单输入值
console.log(text.value)
// 设置表单的值
text.value = '我是一个值'
// 修改属性
text.type = 'password'
const checkbox = document.querySelector('input[type="checkbox"]')
// 为true则有效果(除了空字符串,0都为true布尔值)
checkbox.checked = true
</script>
</body>
</html>

自定义属性
自定义属性规定以data-开头
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<div data-id="1">1</div>
<div data-id="2">2</div>
<div data-id="3">3</div>
<script>
const one = document.querySelector('div')
// .dataset可获取自定义属性集合,是一个对象
console.log(one.dataset)
// 获取自定义属性的值
console.log(one.dataset.id)
</script>
</body>
</html>

定时器
间歇函数
每隔一段时间自动执行一段代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<script>
// 开启定时器(返回一个id数字)
// setInterval(函数,间隔时间)(单位毫秒)
let x = setInterval(function () {
console.log('一秒执行一次')
}, 1000)
function fn() {
console.log('三秒执行一次')
}
// 函数名加小括号是执行
let y = setInterval(fn, 3000)
// 关闭定时器
clearInterval(x)
</script>
</body>
</html>

延时函数
让代码延迟执行的函数,setTimeout(回调函数,等待的毫秒数)
只执行一次
事件监听
事件是在编程时系统内发生的动作或者发生的事情
语法:元素对象.addEventListener('事件类型',要执行的函数)
现在编写一个点击按钮,弹出对话框的示例
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
</head>
<body>
<button>点击</button>
<script>
// 事件源
const btn = document.querySelector('button')
// 事件监听
btn.addEventListener('click', function () {
alert('按钮被点击了~')
})
</script>
</body>
</html>

addEventListener方式可绑定多次,都会执行
鼠标事件
click鼠标点击,mouseenter鼠标经过,mouseleave鼠标离开
焦点事件
focus获得焦点,blur失去焦点
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</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="#">小米16</a></li>
<li><a href="#">小米106</a></li>
<li><a href="#">小米笔记本</a></li>
<li><a href="#">小米手机</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键盘抬起触发
文本事件
input用户输入事件
事件对象
事件对象是对象,存储了事件触发时的相关信息
事件监听的回调函数的第一个参数就是事件对象
部分常用属性:type获取当前的事件类型,clientX/clientY获取光标相对于浏览器可见窗口左上角的位置,offsetX/offsetY获取光标相对于当前DOM元素左上角的位置,key用户按下的键盘键的值
回车发布评论案例
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</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(spring.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-left: 80px;
color: #999;
margin-top: 5px;
opacity: 0;
transition: all 0.5s;
}
.list {
min-width: 400px;
min-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" placeholder="发一条友善的评论" row="2" maxlength="200"></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">2026-2-1 15:43:21</p>
</div>
</div>
</div>
<script>
const tx = document.querySelector('#tx')
const total = document.querySelector('.total')
const item = document.querySelector('.item')
const text = document.querySelector('.text')
// 文本域获得焦点,让total显示出来
tx.addEventListener('focus', function () {
total.style.opacity = 1
})
tx.addEventListener('blur', function () {
total.style.opacity = 0
})
// 更新输入长度
tx.addEventListener('input', function () {
total.innerHTML = `${tx.value.length}/200字`
})
// 按下回车发布评论
tx.addEventListener('keyup', function (e) {
if (e.key === 'Enter') {
// trim()方法可去除字符串左右两侧的空格
if (tx.value.trim() != '') {
item.style.display = 'block'
text.innerHTML = tx.value
}
// 按下完回车,文本域清空
tx.value = ''
total.innerHTML = '0/200字'
}
})
</script>
</body>
</html>

环境对象
环境对象代表着当前函数运行时所处的环境,用this指代
每个函数里面都有this环境对象
回调函数
如果将函数A做为参数传递给函数B时,则称A为回调函数
事件流
事件流指的是事件完整执行过程中的流动路径,分为捕获阶段(从DOM根元素开始去执行对应的事件)和冒泡阶段(事件会在元素的所有祖先元素中依次被触发)
捕获阶段:很少使用,通过addEventListener的第三个参数触发
触发冒泡:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件
阻止冒泡
事件对象.stopPropagation()
此方法可阻断事件流动传播(捕获+冒泡)
解绑事件
匿名函数无法解绑
使用removeEventListener(type,事件处理函数名)方法
事件委托
事件委托就是利用事件冒泡的特点提高程序性能的技巧
给父元素注册事件,当触发子元素时,会冒泡到父元素身上,从而触发父元素的事件
tab栏切换
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</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;
}
img {
width: 400px;
height: 200px;
}
</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="spring.jpg" alt="" /></div>
<div class="item"><img src="summer.jpeg" alt="" /></div>
<div class="item"><img src="antumn.jpg" alt="" /></div>
<div class="item"><img src="winter.jpg" alt="" /></div>
<div class="item"><img src="spring.jpg" alt="" /></div>
</div>
</div>
<script>
const ul = document.querySelector('.tab-nav ul')
ul.addEventListener('click', function (e) { // e是点击的对象
// 只有点击a标签才操作(ul不操作)
if (e.target.tagName === 'A') {
// 先移除原来的active,再当前元素添加active
document.querySelector('.tab-nav .active').classList.remove('active')
e.target.classList.add('active')
const id = parseInt(e.target.dataset.id, 10)
// 移除原来的active,对应图片添加active
document.querySelector('.tab-content .active').classList.remove('active')
document.querySelector(`.tab-content .item:nth-child(${id + 1})`).classList.add('active')
}
})
</script>
</body>
</html>

阻止默认行为
有时提交表单就直接提交了,但信息不正确的情况时,我们要阻止这种默认行为
使用preventDefault()方法
其它页面事件
页面加载事件
有时需要等页面资源全部处理完了再做一些事情
window.addEventListener('load',function(){})
也可以针对某个资源绑定load事件
页面滚动事件
滚动条在滚动的时候持续触发的事件
window.addEventListener('scroll',function(){}),也可以监听某个元素
scrollLeft和scrollTop属性可以获取元素内容往左侧和往上侧滚出去看不到的距离
页面尺寸事件
会在窗口尺寸改变的时候触发事件resize
clientWidth和clientHeight可获取元素可见部分的宽和高
offsetWidth和offsetHeight可获取元素自身的宽和高
offsetLeft和offsetTop是获取元素距离自己定位父级元素的左、上距离
bilibili导航滑动案例
当点击链接时,下方滑块跟着移动
1.事件委托
2.点击链接,则得到当前元素的offsetLeft值
3.修改line颜色块的transform值=点击链接的offsetLeft
日期对象
日期对象是用来表示时间的对象
new关键字实例化时间对象
日期对象有getFullYear()获得年份等方法
时间戳是指1970年1月1日00时00分00秒起至现在的毫秒数,是一种特殊的计量时间方式
将来时间戳-现在时间戳=剩余时间戳
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Page</title>
<style>
.countdown {
width: 240px;
height: 305px;
text-align: center;
line-height: 1;
color: #fff;
background-color: brown;
overflow: hidden;
}
.countdown .next {
font-size: 16px;
margin: 25px 0 14px;
}
.countdown .title {
font-style: 33px;
}
.countdown .tips {
margin-top: 80px;
font-style: 23px;
}
.countdown small {
font-style: 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-style: 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">今天是2026年2月18日</p>
<p class="title">下课倒计时</p>
<p class="clock">
<span id="hour">00</span>
<i>:</i>
<span id="minutes">25</span>
<i>:</i>
<span id="second">20</span>
</p>
<p class="tips">18:30:00下课</p>
</div>
<script>
// 函数封装
function getCountTime() {
// 得到当前的时间戳
const now = +new Date()
// 得到将来的时间戳
const last = +new Date('2026-2-18 18:30:00')
// 转为秒数
const count = (last - now) / 1000
let h = parseInt(count / 60 / 60 % 24)
h = h < 10 ? '0' + h : h
let m = parseInt(count / 60 % 60)
m = m < 10 ? '0' + m : m
let s = parseInt(count % 60)
s = s < 10 ? '0' + s : s
// 写入对应盒子
const hour = document.querySelector('#hour')
const minutes = document.querySelector('#minutes')
const second = document.querySelector('#second')
hour.innerHTML = h
minutes.innerHTML = m
second.innerHTML = s
}
// 页面打开先执行一次
getCountTime()
// 开启定时器
setInterval(getCountTime, 1000)
</script>
</body>
</html>

节点操作
DOM节点
DOM树里每一个内容都称之为节点,主要有以下三种
元素节点:所有标签如body、div
属性节点:所有属性如href
文本节点:所有的文本
查找节点
根据关系来查找节点
父节点查找:返回最近一级的父节点,找不到返回null
子元素.parentNode
子节点查找:childNodes获取所有子节点,包括文本节点、注释节点等
children属性仅获得所有元素节点,返回一个伪数组
查找兄弟节点:nextElementSibling下一个兄弟节点,previousElementSibling上一个兄弟节点
节点操作
发布评论时,新增一条评论,一般通过新增节点的方式
创建节点
创造一个新的网页元素,再添加到网页内
document.createElement('标签名')
增加节点
插入到某个父元素中
插到父元素的最后一个子元素,父元素.appendChild(要插入的元素)
出啊如到父元素的某个子元素的前面,父元素.insertBefore(要插入的元素,在哪个元素前面)
克隆节点
克隆一个已有的元素节点
元素.cloneNode(布尔值),若为true则克隆包含后代节点,若为flase则不包含(默认)
删除节点
在JS元素DOM操作中,删除元素必须通过父元素删除
父元素.removeChild(要删除的元素)
Window对象
BOM
BOM是浏览器对象模型,window对象里面包含DOM对象、location对象、navigator对象、history对象和screen对象。是JS中的顶级对象
因为都在里面,所以window对象下的属性和方法调用的时候可以省略window
JS执行机制
浏览器有两个引擎,一个渲染引擎,渲染html、css;另一个是JS解释器,解析JS
html
consle.log(1)
setTimeout(function(){
console.log(2)
},1000)
console.log(3)
上述代码输出132
html
consle.log(1)
setTimeout(function(){
console.log(2)
},0)
console.log(3)
上述代码也输出132
JS语言的一大特点就是单线程,同一时间只能做一件事。为了解决这个问题,利用多核CPU的计算能力,JS中出现了同步和异步
同步:前一个任务结束后再执行后一个任务
异步:在做一件事情时,可以去处理其它事情
JS的异步是通过回调函数实现的
JS先执行执行栈中的同步任务,异步任务放入任务队列中,一旦执行栈中的所有同步任务执行完毕,系统会按序读取任务队列中的异步任务
location对象
拆分并保存了URL地址的各个组成部分
href属性获取完整的URL地址,对其赋值用于地址的跳转
search属性可以获取地址中携带的参数(?后面的部分)
hash属性获取地址中的哈希值(#后面的部分)
reload方法用来刷新当前页面
navigator对象
navigator对象记录了浏览器自身的相关信息
通过userAgent属性检测浏览器的版本及平台,分移动端、网页端
hisory对象
管理浏览器地址栏相关操作(前进、后退)历史记录
本地存储
数据存储在用户浏览器中,页面刷新数据不丢失
localStorage
可以将数据永久存储在用户电脑,关闭页面也不会丢失,除非手动删除
存储/修改数据:localStorage.setItem(key,value)

获取数据:localStorage.getItem(key)
删除数据:localStorage.removeItem(key)
只能存储字符串,不能存储复杂数据类型。需将复杂数据类型转换成JSON字符串存储到本地JSON.stringify(对象)
把取出来的字符串转换为对象JSON.parse(JSON字符串)
sessionStorage
生命周期为关闭浏览器窗口,在同一个窗口下数据可共享
字符串
map()和join()方法
map()方法可以遍历数组处理数据,并返回新的数组,也称为映射
join()方法用于把数组中的所有元素拼接成一个字符串
正则表达式
正则表达式用于匹配字符暗藏中字符组合的模式,在JS中正则表达式也是对象
可用于表单验证、过滤敏感词、提取想要的部分
定义正则表达式:const 变量名 = /正则表达式/
判断是否有符合规则的字符串:规则.test(被检测的字符串)
普通字符只能匹配字符串中与它们相同的字符
元字符是一些具有特殊含义的字符,提高了匹配功能,分为:
边界符,用于提示字符所处的位置,^以谁开始,$以谁结束
量词,用于表示重复次数,*重复零次或更多次,+重复一次或更多次,?重复零次或一次,{n}重复n次,{n,}重复>=n次,{n,m}重复n到m次
字符类,[]匹配字符集合(后面的字符串只有包含任意一个字符就返回true),[ - ]表示一个范围,\d匹配0-9之间的任一数字,\w匹配任意字母......
修饰符用于约束正则执行的某些细节,i是ignore的缩写,如正则匹配时不区分大小写,g是global,匹配所有满足正则表达式的结果
替换replace字符串.replace(/正则表达式/,'替换的文本')
插件的使用
一个插件官网https:www.swiper.com.cn/
下载

css文件包和js文件包在package文件夹里面,可以直接复制过去
也可以直接演示,然后复制想要的文件源代码
