本系列:(一)JavaScript基础 第1-2天 · (二)JavaScript基础 第3-5天 · (三)Web APIs 第1-3天 · (四)Web APIs 第4-6天与个人实战

Web APIs - 第4天

进一步学习 DOM 相关知识,实现可交互的网页特效

  • 能够插入、删除和替换元素节点
  • 能够依据元素节点关系查找节点

日期对象

掌握 Date 日期对象的使用,动态获取当前计算机的时间。

ECMAScript 中内置了获取系统时间的对象 Date,使用 Date 时与之前学习的内置对象 console 和 Math 不同,它需要借助 new 关键字才能使用。

实例化

1
2
3
4
5
6
7
8
9
// 1. 实例化
// const date = new Date(); // 系统默认时间
const date = new Date('2020-05-01') // 指定时间
// date 变量即所谓的时间对象

console.log(typeof date)



方法

1
2
3
4
5
6
 // 1. 实例化
const date = new Date();
// 2. 调用时间对象方法
// 通过方法分别获取年、月、日,时、分、秒
const year = date.getFullYear(); // 四位年份
const month = date.getMonth(); // 0 ~ 11

getFullYear 获取四位年份

getMonth 获取月份,取值为 0 ~ 11

getDate 获取月份中的每一天,不同月份取值也不相同

getDay 获取星期,取值为 0 ~ 6

getHours 获取小时,取值为 0 ~ 23

getMinutes 获取分钟,取值为 0 ~ 59

getSeconds 获取秒,取值为 0 ~ 59

时间戳

时间戳是指1970年01月01日00时00分00秒起至现在的总秒数或毫秒数,它是一种特殊的计量时间的方式。

注:ECMAScript 中时间戳是以毫秒计的。

1
2
3
4
5
6
7
8
9
    // 1. 实例化
const date = new Date()
// 2. 获取时间戳
console.log(date.getTime())
// 还有一种获取时间戳的方法
console.log(+new Date())
// 还有一种获取时间戳的方法
console.log(Date.now())

获取时间戳的方法,分别为 getTime 和 Date.now 和 +new Date()

DOM 节点

掌握元素节点创建、复制、插入、删除等操作的方法,能够依据元素节点的结构关系查找节点

回顾之前 DOM 的操作都是针对元素节点的属性或文本的,除此之外也有专门针对元素节点本身的操作,如插入、复制、删除、替换等。

插入节点

在已有的 DOM 节点中插入新的 DOM 节点时,需要关注两个关键因素:首先要得到新的 DOM 节点,其次在哪个位置插入这个节点。

如下代码演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<body>
<h3>插入节点</h3>
<p>在现有 dom 结构基础上插入新的元素节点</p>
<hr>
<!-- 普通盒子 -->
<div class="box"></div>
<!-- 点击按钮向 box 盒子插入节点 -->
<button class="btn">插入节点</button>
<script>
// 点击按钮,在网页中插入节点
const btn = document.querySelector('.btn')
btn.addEventListener('click', function () {
// 1. 获得一个 DOM 元素节点
const p = document.createElement('p')
p.innerText = '创建的新的p标签'
p.className = 'info'

// 复制原有的 DOM 节点
const p2 = document.querySelector('p').cloneNode(true)
p2.style.color = 'red'

// 2. 插入盒子 box 盒子
document.querySelector('.box').appendChild(p)
document.querySelector('.box').appendChild(p2)
})
</script>
</body>

结论:

  • createElement 动态创建任意 DOM 节点

  • cloneNode 复制现有的 DOM 节点,传入参数 true 会复制所有子节点

  • appendChild 在末尾(结束标签前)插入节点

再来看另一种情形的代码演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<body>
<h3>插入节点</h3>
<p>在现有 dom 结构基础上插入新的元素节点</p>
<hr>
<button class="btn1">在任意节点前插入</button>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
<script>
// 点击按钮,在已有 DOM 中插入新节点
const btn1 = document.querySelector('.btn1')
btn1.addEventListener('click', function () {

// 第 2 个 li 元素
const relative = document.querySelector('li:nth-child(2)')

// 1. 动态创建新的节点
const li1 = document.createElement('li')
li1.style.color = 'red'
li1.innerText = 'Web APIs'

// 复制现有的节点
const li2 = document.querySelector('li:first-child').cloneNode(true)
li2.style.color = 'blue'

// 2. 在 relative 节点前插入
document.querySelector('ul').insertBefore(li1, relative)
document.querySelector('ul').insertBefore(li2, relative)
})
</script>
</body>

结论:

  • createElement 动态创建任意 DOM 节点

  • cloneNode 复制现有的 DOM 节点,传入参数 true 会复制所有子节点

  • insertBefore 在父节点中任意子节点之前插入新节点

删除节点

删除现有的 DOM 节点,也需要关注两个因素:首先由父节点删除子节点,其次是要删除哪个子节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<!-- 点击按钮删除节点 -->
<button>删除节点</button>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>Web APIs</li>
</ul>

<script>
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
// 获取 ul 父节点
let ul = document.querySelector('ul')
// 待删除的子节点
let lis = document.querySelectorAll('li')

// 删除节点
ul.removeChild(lis[0])
})
</script>
</body>

结论:removeChild 删除节点时一定是由父子关系。

查找节点

DOM 树中的任意节点都不是孤立存在的,它们要么是父子关系,要么是兄弟关系,不仅如此,我们可以依据节点之间的关系查找节点。

父子关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<button class="btn1">所有的子节点</button>
<!-- 获取 ul 的子节点 -->
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript 基础</li>
<li>Web APIs</li>
</ul>
<script>
const btn1 = document.querySelector('.btn1')
btn1.addEventListener('click', function () {
// 父节点
const ul = document.querySelector('ul')

// 所有的子节点
console.log(ul.childNodes)
// 只包含元素子节点
console.log(ul.children)
})
</script>
</body>

结论:

  • childNodes 获取全部的子节点,回车换行会被认为是空白文本节点
  • children 只获取元素类型节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<body>
<table>
<tr>
<td width="60">序号</td>
<td>课程名</td>
<td>难度</td>
<td width="80">操作</td>
</tr>
<tr>
<td>1</td>
<td><span>HTML</span></td>
<td>初级</td>
<td><button>变色</button></td>
</tr>
<tr>
<td>2</td>
<td><span>CSS</span></td>
<td>初级</td>
<td><button>变色</button></td>
</tr>
<tr>
<td>3</td>
<td><span>Web APIs</span></td>
<td>中级</td>
<td><button>变色</button></td>
</tr>
</table>
<script>
// 获取所有 button 节点,并添加事件监听
const buttons = document.querySelectorAll('table button')
for(let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function () {
// console.log(this.parentNode); // 父节点 td
// console.log(this.parentNode.parentNode); // 爷爷节点 tr
this.parentNode.parentNode.style.color = 'red'
})
}
</script>
</body>

结论:parentNode 获取父节点,以相对位置查找节点,实际应用中非常灵活。

兄弟关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript 基础</li>
<li>Web APIs</li>
</ul>
<script>
// 获取所有 li 节点
const lis = document.querySelectorAll('ul li')

// 对所有的 li 节点添加事件监听
for(let i = 0; i < lis.length; i++) {
lis[i].addEventListener('click', function () {
// 前一个节点
console.log(this.previousSibling)
// 下一下节点
console.log(this.nextSibling)
})
}
</script>
</body>

结论:

  • previousSibling 获取前一个节点,以相对位置查找节点,实际应用中非常灵活。
  • nextSibling 获取后一个节点,以相对位置查找节点,实际应用中非常灵活。

Web APIs - 第5天笔记

目标: 能够利用JS操作浏览器,具备利用本地存储实现学生就业表的能力

  • BOM操作
  • 综合案例

js组成

JavaScript的组成

  • ECMAScript:

    • 规定了js基础语法核心知识。
    • 比如:变量、分支语句、循环语句、对象等等
  • Web APIs :

    • DOM 文档对象模型, 定义了一套操作HTML文档的API
    • BOM 浏览器对象模型,定义了一套操作浏览器窗口的API

67604738945

window对象

BOM (Browser Object Model ) 是浏览器对象模型

  • window对象是一个全局对象,也可以说是JavaScript中的顶级对象
  • 像document、alert()、console.log()这些都是window的属性,基本BOM的属性和方法都是window的
  • 所有通过var定义在全局作用域中的变量、函数都会变成window对象的属性和方法
  • window对象下的属性和方法调用的时候可以省略window

67604743636

定时器-延迟函数

JavaScript 内置的一个用来让代码延迟执行的函数,叫 setTimeout

语法:

1
setTimeout(回调函数, 延迟时间)

setTimeout 仅仅只执行一次,所以可以理解为就是把一段代码延迟执行, 平时省略window

间歇函数 setInterval : 每隔一段时间就执行一次, , 平时省略window

清除延时函数:

1
clearTimeout(timerId)

注意点

  1. 延时函数需要等待,所以后面的代码先执行
  2. 返回值是一个正整数,表示定时器的编号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<body>
<script>
// 定时器之延迟函数

// 1. 开启延迟函数
let timerId = setTimeout(function () {
console.log('我只执行一次')
}, 3000)

// 1.1 延迟函数返回的还是一个正整数数字,表示延迟函数的编号
console.log(timerId)

// 1.2 延迟函数需要等待时间,所以下面的代码优先执行

// 2. 关闭延迟函数
clearTimeout(timerId)

</script>
</body>

location对象

location (地址) 它拆分并保存了 URL 地址的各个组成部分, 它是一个对象

属性/方法 说明
href 属性,获取完整的 URL 地址,赋值时用于地址的跳转
search 属性,获取地址中携带的参数,符号 ?后面部分
hash 属性,获取地址中的啥希值,符号 # 后面部分
reload() 方法,用来刷新当前页面,传入参数 true 时表示强制刷新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<body>
<form>
<input type="text" name="search"> <button>搜索</button>
</form>
<a href="#/music">音乐</a>
<a href="#/download">下载</a>

<button class="reload">刷新页面</button>
<script>
// location 对象
// 1. href属性 (重点) 得到完整地址,赋值则是跳转到新地址
console.log(location.href)
// location.href = 'http://www.itcast.cn'

// 2. search属性 得到 ? 后面的地址
console.log(location.search) // ?search=笔记本

// 3. hash属性 得到 # 后面的地址
console.log(location.hash)

// 4. reload 方法 刷新页面
const btn = document.querySelector('.reload')
btn.addEventListener('click', function () {
// location.reload() // 页面刷新
location.reload(true) // 强制页面刷新 ctrl+f5
})
</script>
</body>

navigator是对象,该对象下记录了浏览器自身的相关信息

常用属性和方法:

  • 通过 userAgent 检测浏览器的版本及平台
1
2
3
4
5
6
7
8
9
10
// 检测 userAgent(浏览器信息)
(function () {
const userAgent = navigator.userAgent
// 验证是否为Android或iPhone
const 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'
}})();

histroy对象

history (历史)是对象,主要管理历史记录, 该对象与浏览器地址栏的操作相对应,如前进、后退等

使用场景

history对象一般在实际开发中比较少用,但是会在一些OA 办公系统中见到。

67604783479

常见方法:

67604784659

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<body>
<button class="back">←后退</button>
<button class="forward">前进→</button>
<script>
// histroy对象

// 1.前进
const forward = document.querySelector('.forward')
forward.addEventListener('click', function () {
// history.forward()
history.go(1)
})
// 2.后退
const back = document.querySelector('.back')
back.addEventListener('click', function () {
// history.back()
history.go(-1)
})
</script>
</body>

本地存储(今日重点)

本地存储:将数据存储在本地浏览器中

常见的使用场景:

https://todomvc.com/examples/vanilla-es6/ 页面刷新数据不丢失

好处:

1、页面刷新或者关闭不丢失数据,实现数据持久化

2、容量较大,sessionStorage和 localStorage 约 5M 左右

localStorage(重点)

作用: 数据可以长期保留在本地浏览器中,刷新页面和关闭页面,数据也不会丢失

特性:以键值对的形式存储,并且存储的是字符串, 省略了window

67604963508

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!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>本地存储-localstorage</title>
</head>

<body>
<script>
// 本地存储 - localstorage 存储的是字符串
// 1. 存储
localStorage.setItem('age', 18)

// 2. 获取
console.log(typeof localStorage.getItem('age'))

// 3. 删除
localStorage.removeItem('age')
</script>
</body>

</html>

sessionStorage(了解)

特性:

  • 用法跟localStorage基本相同
  • 区别是:当页面浏览器被关闭时,存储在 sessionStorage 的数据会被清除

存储:sessionStorage.setItem(key,value)

获取:sessionStorage.getItem(key)

删除:sessionStorage.removeItem(key)

localStorage 存储复杂数据类型

问题:本地只能存储字符串,无法存储复杂数据类型.

解决:需要将复杂数据类型转换成 JSON字符串,在存储到本地

语法:JSON.stringify(复杂数据类型)

JSON字符串:

  • 首先是1个字符串
  • 属性名使用双引号引起来,不能单引号
  • 属性值如果是字符串型也必须双引号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<body>
<script>
// 本地存储复杂数据类型
const goods = {
name: '小米',
price: 1999
}
// localStorage.setItem('goods', goods)
// console.log(localStorage.getItem('goods'))

// 1. 把对象转换为JSON字符串 JSON.stringify
localStorage.setItem('goods', JSON.stringify(goods))
// console.log(typeof localStorage.getItem('goods'))

</script>
</body>

问题:因为本地存储里面取出来的是字符串,不是对象,无法直接使用

解决:把取出来的字符串转换为对象

语法:JSON.parse(JSON字符串)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<body>
<script>
// 本地存储复杂数据类型
const goods = {
name: '小米',
price: 1999
}
// localStorage.setItem('goods', goods)
// console.log(localStorage.getItem('goods'))

// 1. 把对象转换为JSON字符串 JSON.stringify
localStorage.setItem('goods', JSON.stringify(goods))
// console.log(typeof localStorage.getItem('goods'))

// 2. 把JSON字符串转换为对象 JSON.parse
console.log(JSON.parse(localStorage.getItem('goods')))

</script>
</body>

综合案例

数组map 方法

使用场景:

map 可以遍历数组处理数据,并且返回新的数组

语法:

1
2
3
4
5
6
7
8
9
10
11
12
<body>
<script>
const arr = ['red', 'blue', 'pink']
// 1. 数组 map方法 处理数据并且 返回一个数组
const newArr = arr.map(function (ele, index) {
// console.log(ele) // 数组元素
// console.log(index) // 索引号
return ele + '颜色'
})
console.log(newArr)
</script>
</body>

map 也称为映射。映射是个术语,指两个元素的集之间元素相互“对应”的关系。

map重点在于有返回值,forEach没有返回值(undefined)

数组join方法

作用:join() 方法用于把数组中的所有元素转换一个字符串

语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<body>
<script>
const arr = ['red', 'blue', 'pink']

// 1. 数组 map方法 处理数据并且 返回一个数组
const newArr = arr.map(function (ele, index) {
// console.log(ele) // 数组元素
// console.log(index) // 索引号
return ele + '颜色'
})
console.log(newArr)

// 2. 数组join方法 把数组转换为字符串
// 小括号为空则逗号分割
console.log(newArr.join()) // red颜色,blue颜色,pink颜色
// 小括号是空字符串,则元素之间没有分隔符
console.log(newArr.join('')) //red颜色blue颜色pink颜色
console.log(newArr.join('|')) //red颜色|blue颜色|pink颜色
</script>
</body>

Web APIs - 第6天笔记

目标:能够利用正则表达式完成小兔鲜注册页面的表单验证,具备常见的表单验证能力

  • 正则表达式
  • 综合案例
  • 阶段案例

正则表达式

正则表达式(Regular Expression)是一种字符串匹配的模式(规则)

使用场景:

  • 例如验证表单:手机号表单要求用户只能输入11位的数字 (匹配)
  • 过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等

67607966636

正则基本使用

  1. 定义规则

    1
    const reg =  /表达式/
    • 其中/ /是正则表达式字面量
    • 正则表达式也是对象
  2. 使用正则

    • test()方法 用来查看正则表达式与指定的字符串是否匹配
    • 如果正则表达式与指定的字符串匹配 ,返回true,否则false
1
2
3
4
5
6
7
8
9
10
11
12
<body>
<script>
// 正则表达式的基本使用
const str = 'web前端开发'
// 1. 定义规则
const reg = /web/

// 2. 使用正则 test()
console.log(reg.test(str)) // true 如果符合规则匹配上则返回true
console.log(reg.test('java开发')) // false 如果不符合规则匹配上则返回 false
</script>
</body>

元字符

  1. 普通字符:
  • 大多数的字符仅能够描述它们本身,这些字符称作普通字符,例如所有的字母和数字。
  • 普通字符只能够匹配字符串中与它们相同的字符。
  • 比如,规定用户只能输入英文26个英文字母,普通字符的话 /[abcdefghijklmnopqrstuvwxyz]/
  1. 元字符(特殊字符)
  • 是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能。
  • 比如,规定用户只能输入英文26个英文字母,换成元字符写法: /[a-z]/

边界符

正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符

67608008165

如果 ^ 和 $ 在一起,表示必须是精确匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<body>
<script>
// 元字符之边界符
// 1. 匹配开头的位置 ^
const reg = /^web/
console.log(reg.test('web前端')) // true
console.log(reg.test('前端web')) // false
console.log(reg.test('前端web学习')) // false
console.log(reg.test('we')) // false

// 2. 匹配结束的位置 $
const reg1 = /web$/
console.log(reg1.test('web前端')) // false
console.log(reg1.test('前端web')) // true
console.log(reg1.test('前端web学习')) // false
console.log(reg1.test('we')) // false

// 3. 精确匹配 ^ $
const reg2 = /^web$/
console.log(reg2.test('web前端')) // false
console.log(reg2.test('前端web')) // false
console.log(reg2.test('前端web学习')) // false
console.log(reg2.test('we')) // false
console.log(reg2.test('web')) // true
console.log(reg2.test('webweb')) // flase
</script>
</body>

量词

量词用来设定某个模式重复次数

67608018538

注意: 逗号左右两侧千万不要出现空格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<body>
<script>
// 元字符之量词
// 1. * 重复次数 >= 0 次
const reg1 = /^w*$/
console.log(reg1.test('')) // true
console.log(reg1.test('w')) // true
console.log(reg1.test('ww')) // true
console.log('-----------------------')

// 2. + 重复次数 >= 1 次
const reg2 = /^w+$/
console.log(reg2.test('')) // false
console.log(reg2.test('w')) // true
console.log(reg2.test('ww')) // true
console.log('-----------------------')

// 3. ? 重复次数 0 || 1
const reg3 = /^w?$/
console.log(reg3.test('')) // true
console.log(reg3.test('w')) // true
console.log(reg3.test('ww')) // false
console.log('-----------------------')


// 4. {n} 重复 n 次
const reg4 = /^w{3}$/
console.log(reg4.test('')) // false
console.log(reg4.test('w')) // flase
console.log(reg4.test('ww')) // false
console.log(reg4.test('www')) // true
console.log(reg4.test('wwww')) // false
console.log('-----------------------')

// 5. {n,} 重复次数 >= n
const reg5 = /^w{2,}$/
console.log(reg5.test('')) // false
console.log(reg5.test('w')) // false
console.log(reg5.test('ww')) // true
console.log(reg5.test('www')) // true
console.log('-----------------------')

// 6. {n,m} n =< 重复次数 <= m
const reg6 = /^w{2,4}$/
console.log(reg6.test('w')) // false
console.log(reg6.test('ww')) // true
console.log(reg6.test('www')) // true
console.log(reg6.test('wwww')) // true
console.log(reg6.test('wwwww')) // false

// 7. 注意事项: 逗号两侧千万不要加空格否则会匹配失败

</script>

范围

表示字符的范围,定义的规则限定在某个范围,比如只能是英文字母,或者数字等等,用表示范围

67608029616

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<body>
<script>
// 元字符之范围 []
// 1. [abc] 匹配包含的单个字符, 多选1
const reg1 = /^[abc]$/
console.log(reg1.test('a')) // true
console.log(reg1.test('b')) // true
console.log(reg1.test('c')) // true
console.log(reg1.test('d')) // false
console.log(reg1.test('ab')) // false

// 2. [a-z] 连字符 单个
const reg2 = /^[a-z]$/
console.log(reg2.test('a')) // true
console.log(reg2.test('p')) // true
console.log(reg2.test('0')) // false
console.log(reg2.test('A')) // false
// 想要包含小写字母,大写字母 ,数字
const reg3 = /^[a-zA-Z0-9]$/
console.log(reg3.test('B')) // true
console.log(reg3.test('b')) // true
console.log(reg3.test(9)) // true
console.log(reg3.test(',')) // flase

// 用户名可以输入英文字母,数字,可以加下划线,要求 6~16位
const reg4 = /^[a-zA-Z0-9_]{6,16}$/
console.log(reg4.test('abcd1')) // false
console.log(reg4.test('abcd12')) // true
console.log(reg4.test('ABcd12')) // true
console.log(reg4.test('ABcd12_')) // true

// 3. [^a-z] 取反符
const reg5 = /^[^a-z]$/
console.log(reg5.test('a')) // false
console.log(reg5.test('A')) // true
console.log(reg5.test(8)) // true

</script>
</body>

字符类

某些常见模式的简写方式,区分字母和数字

67608035363

67608037232

替换和修饰符

replace 替换方法,可以完成字符的替换

67608043716

1
2
3
4
5
6
7
8
9
<body>
<script>
// 替换和修饰符
const str = '欢迎大家学习前端,相信大家一定能学好前端,都成为前端大神'
// 1. 替换 replace 需求:把前端替换为 web
// 1.1 replace 返回值是替换完毕的字符串
// const strEnd = str.replace(/前端/, 'web') 只能替换一个
</script>
</body>

修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等

  • i 是单词 ignore 的缩写,正则匹配时字母不区分大小写
  • g 是单词 global 的缩写,匹配所有满足正则表达式的结果
1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
<script>
// 替换和修饰符
const str = '欢迎大家学习前端,相信大家一定能学好前端,都成为前端大神'
// 1. 替换 replace 需求:把前端替换为 web
// 1.1 replace 返回值是替换完毕的字符串
// const strEnd = str.replace(/前端/, 'web') 只能替换一个

// 2. 修饰符 g 全部替换
const strEnd = str.replace(/前端/g, 'web')
console.log(strEnd)
</script>
</body>

正则插件

67608054863

change 事件

给input注册 change 事件,值被修改并且失去焦点后触发

判断是否有类

67608061879

元素.classList.contains() 看看有没有包含某个类,如果有则返回true,么有则返回false

个人实战文档

本次实战是对自己整个api阶段的总结。

参考效果如下地址:

http://erabbit.itheima.net/#/product/3995139

本次实战主要分为以下几个模块。

顶部导航模块

需求:

  1. 顶部导航开始不显示
  2. 等页面滑到主导航栏,这个新顶部导航栏滑动下拉显示,并且改为固定定位
  3. 等页面滑到上面,新顶部导航栏隐藏

图片切换模块

放大镜效果

业务分析:

①:鼠标经过对应小盒子,左侧中等盒子显示对应中等图片

②: 鼠标经过中盒子,右侧会显示放大镜效果的大盒子

③: 黑色遮罩盒子跟着鼠标来移动

④: 鼠标在中等盒子上移动,大盒子的图片跟着显示对应位置

思路分析:

①:鼠标经过小盒子,左侧中等盒子显示对应中等图片

  1. 获取对应的元素
  2. 采取事件委托的形式,监听鼠标经过小盒子里面的图片, 注意此时需要使用 mouseover 事件,因为需要事件冒泡触发small
  3. 让鼠标经过小图片的爸爸li盒子,添加类,其余的li移除类(注意先移除,后添加)
  4. 鼠标经过小图片,可以拿到小图片的src, 可以做两件事
    • 让中等盒子的图片换成这个 这个小图片的src
    • 让大盒子的背景图片,也换成这个小图片的 src (稍后做)

②: 鼠标经过中等盒子,右侧大盒子显示

  1. 用到鼠标经过和离开,鼠标经过中盒子,大盒子 利用 display 来显示和隐藏

  2. 鼠标离开不会立马消失,而是有200ms的延时,用户体验更好,所以尽量使用定时器做个延时 setTimeout

  3. 显示和隐藏也尽量定义一个函数,因为鼠标经过离开中等盒子,会显示隐藏,同时,鼠标经过大盒子,也会显示和隐藏

  4. 给大盒子里面的背景图片一个默认的第一张图片

③: 黑色遮罩盒子跟着鼠标来移动

  1. 先做鼠标经过 中等盒子,显示隐藏 黑色遮罩 的盒子

  2. 让黑色遮罩跟着鼠标来走, 需要用到鼠标移动事件 mousemove

  3. 让黑色盒子的移动的核心思想:不断把鼠标在中等盒子内的坐标给黑色遮罩层 let top 值,这样遮罩层就可以跟着移动了

    • 需求

      • 我们要的是 鼠标在 中等盒子内的坐标, 没有办法直接得到
      • 得到1: 鼠标在页面中的坐标
      • 得到2: 中等盒子在页面中的坐标
    • 算法

      • 得到鼠标在页面中的坐标 利用事件对象的 pageX
      • 得到middle中等盒子在页面中的坐标 middle.getBoundingClientRect()
      • 鼠标在middle 盒子里面的坐标 = 鼠标在页面中的坐标 - middle 中等盒子的坐标
      • 黑色遮罩层不断得到 鼠标在middle 盒子中的坐标 就可以移动起来了

      注意 y坐标特殊,需要减去 页面被卷去的头部

      为什么不用 box.offsetLet 和 box.offsetTop 因为这俩属性跟带有定位的父级有关系,很容被父级影响,而getBoundingClientRect() 不受定位的父元素的影响

    • 限定遮罩的盒子只能在middle 内部移动,需要添加判断

      • 限定水平方向 大于等于0 并且小于等于 400
      • 限定垂直方向 大于等于0 并且小于等于 400
    • 遮罩盒子移动的坐标:

      • 声明一个 mx 作为移动的距离
      • 水平坐标 x 如果 小于等于100 ,则移动的距离 mx 就是 0 不应该移动
      • 水平坐标 如果 大于等于100 并且小于300,移动的距离就是 mx - 100 (100是遮罩盒子自身宽度的一半)
      • 水平坐标 如果 大于等于300,移动的距离就是 mx 就是200 不应该在移动了
      • 其实我们发现水平移动, 就在 100 ~ 200 之间移动的
      • 垂直同理
    1
    2
    3
    4
    5
    6
    7
    8
    let mx = 0, my = 0;
    if (x <= 100) mx = 0
    if (x > 100 && x < 300) mx = x - 100
    if (x >= 300) mx = 200

    if (y <= 100) my = 0
    if (y > 100 && y < 300) my = y - 100
    if (y >= 300) my = 200
    • 大盒子图片移动的计算方法:
      • 中等盒子是 400px 大盒子 是 800px 的图片
      • 中等盒子移动1px, 大盒子就应该移动2px, 只不过是负值
    1
    2
    large.style.backgroundPositionX = - 2 * mx + 'px'
    large.style.backgroundPositionY = - 2 * my + 'px'

    放大镜完整代码:

其他模块

此模块可以根据自己时间添加

点击模块

tab栏切换模块

返回顶部模块

页面滚动底部,可以出现一个侧边栏,点击返回顶部,可以返回顶部