webApi第7天
本地存储
本地存储特性
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。 1、数据存储在用户浏览器中 2、设置、读取方便、甚至页面刷新不丢失数据 3、容量较大,sessionStorage和localStorage约 5M 左右
localStorage
1、生命周期永久生效,除非手动删除 否则关闭页面也会存在 2、可以多窗口(页面)共享(同一浏览器可以共享)
- 以键值对的形式存储使用
存储复杂数据类型存储 本地只能存储字符串,无法存储复杂数据类型.需要将复杂数据类型转换成JSON字符串,在存储到本地 JSON.stringify(复杂数据类型) 将复杂数据转换成JSON字符串 存储 本地存储中 JSON.parse(JSON字符串) 将JSON字符串转换成对象 取出 时候使用
页面背景颜色--本地存储案例
<body>
<input type="color">
<script>
//body背景颜色等于本地存储中的颜色
document.body.style.backgroundColor = localStorage.getItem('color')
//获取colorinput标签 并绑定改变事件
let colorDom = document.querySelector('input')
colorDom.addEventListener('change',function () {
// console.log(colorDom.value );
//设置背景颜色为colorinput的颜色
document.body.style.backgroundColor = colorDom.value
//设置input的颜色值到本地村粗中
localStorage.setItem('color',`${colorDom.value}`)
})
</script>
</body>
学生就业薪资+本地存储-案例
<!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>08-综合案例-模版</title>
<style>
* {
margin: 0;
padding: 0;
}
a {
text-decoration: none;
color: #721c24;
}
h1 {
text-align: center;
color: #333;
margin: 20px 0;
}
table {
margin: 0 auto;
width: 800px;
border-collapse: collapse;
color: #004085;
}
th {
padding: 10px;
background: #cfe5ff;
font-size: 20px;
font-weight: 400;
}
td,
th {
border: 1px solid #b8daff;
}
td {
padding: 10px;
color: #666;
text-align: center;
font-size: 16px;
}
tbody tr {
background: #fff;
}
tbody tr:hover {
background: #e1ecf8;
}
.info {
width: 900px;
margin: 50px auto;
text-align: center;
}
.info input {
width: 80px;
height: 25px;
outline: none;
border-radius: 5px;
border: 1px solid #b8daff;
padding-left: 5px;
}
.info button {
width: 60px;
height: 25px;
background-color: #004085;
outline: none;
border: 0;
color: #fff;
cursor: pointer;
border-radius: 5px;
}
.info .age {
width: 50px;
}
</style>
</head>
<body>
<h1>新增学员</h1>
<div class="info">
姓名:<input type="text" class="uname" /> 年龄:<input
type="text"
class="age"
/>
性别:
<select name="gender" id="" class="gender">
<option value="男">男</option>
<option value="女">女</option>
</select>
薪资:<input type="text" class="salary" /> 就业城市:<select
name="city"
id=""
class="city"
>
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
<option value="曹县">曹县</option>
</select>
<button class="add">录入</button>
</div>
<h1>就业榜</h1>
<table>
<thead>
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>薪资</th>
<th>就业城市</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- <tr>
<td>1</td>
<td>这是名称</td>
<td>这是年龄</td>
<td>这是性别</td>
<td>这是工资</td>
<td>这是所在城市</td>
<td>
<a href="javascript:" class="del">删除</a>
</td>
</tr> -->
</tbody>
</table>
<script>
// 1.1 定义数组 负责存放表格要显示的数据
// 获取本地存储中的数组(字符串格式) 转成 数组格式
// 第一次打开页面的时候 ,本地存储里面会有数据吗
const newArr = localStorage.getItem('arr')
let arr = [];
if (newArr){
arr = JSON.parse(newArr)
}else {arr = 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);
//数组转字符串
const strArr = JSON.stringify(arr)
//本地存储
localStorage.setItem('arr',strArr)
// 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);
//数组转字符串
const strArr = JSON.stringify(arr)
//本地存储
localStorage.setItem('arr',strArr)
// 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>
</body>
</html>
sessionStorage
- sessionStorage 本地存储的用法和 localStorage 是一样的。
- 区别在于:只是他存储的数据 在关闭页面后 ,数据就会丢失。localStorage 会一直保存着,除非手动删除。
<body>
<script>
sessionStorage.setItem('abc',123)
sessionStorage.getItem('abc')
/*
本地存储的技术 sessionStorage 会话(打开页面到关闭页面之间过程 一次会话 ajax node)存储
登录的时候
它的用法和 localStorage 用法一样
区别只有一个
sessionStorage 关闭页面后 数据就丢失
localStorage 除非是用户主动删除 否则一直存在 直到天荒地老
*/
// 存数据
// sessionStorage.setItem("ss",123);
// 取数据
// console.log(sessionStorage.getItem("ss"));
// 删除一个
// sessionStorage.removeItem("ss")
// 清空
// sessionStorage.clear();
</script>
</body>
元素属性
固有属性
1.标签的固有属性 比如a标签的href属性,img标签的src属性 各标签的id属性等 获取和设置比较方便 可以直接使用 . 语法
<body>
<a data-index="0" id="nav" href="http://www.baidu.com" hello="no" aa="bb" >跳转</a >
<script>
const a = document.querySelector('a');
// 获取固有属性
console.log(a.href);
console.log(a.id);
// 直接修改
a.href="http://www.qq.com";
a.id="top";
</script>
</body>
自定义属性
-
自己给标签创建的属性名,不能通过 . 语法来获取和设置。
-
获取 getAttribute("属性名")
-
设置/添加、修改 setAttribute("属性名",修改的内容)
-
删除属性 removeAttribute ("要删除的属性名")
<body>
<a data-index="0" id="nav" href="#" hello="no" aa="bb" >跳转</a >
<script>
const a = document.querySelector('a');
// 自定义属性 不能直接通过点语法来获取和设置
// 获取 getAttribute("属性名")
console.log( a.getAttribute("hello") );
console.log( a.getAttribute("aa") );
// 设置/添加、修改 setAttribute(key,value)
//标签已有该属性名为修改 没有为添加
a.setAttribute("hell0","123");
a.setAttribute("hell","123");
// 删除属性 removeAttribute(key)
a.removeAttribute("hello");
</script>
</body>
html5建议的自定义属性
-
属性: data-xxx 开头;
-
获取: a.dataset.xxx;
-
设置: 元素.dataset.xxx = 自定义的取值;
<body>
<a data-index="0" id="nav" href="http://www.baidu.com">跳转</a >
<script>
// 自定义属性 -> h5建议的 自定义属性
// 属性的时候 data-xxx 开头
// 获取的时候 a.dataset.xxx
// 设置 a.dataset.index = 3;
// console.log(a.dataset.index);
// a.dataset.index = 3;
</script>
</body>
小结
标签的属性 有两种分为
-
固有属性 比如 id href src 点语法的方式获取和设置 方便
-
自定义属性
1. 随意自己命名
<a abc="123" >
获取 getAttribute(key) 设置 setAttribute(key,value) 删除 removeAttribute(key)
2 . h5建议 data- xxx
<a data-abc="123" >
获取(a.dataset.abc) 设置(a.dataset.abc=456);
- 最强大是 (getAttribute) setAttribute removeAttribute
上述的这个方式,可以获取到任意的属性(固有属性和h5建议的自定义属性)
高阶函数
一个函数a 可以把另一个函数b 当成参数来接收处理,或者返回另外一个新的函数c。
如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为回调函数 简单理解: 当一个函数当做参数来传递给另外一个函数的时候,这个函数就是回调函数
- 高阶函数可以被简单理解为函数的高级应用,JavaScript 中函数可以被当成【值】来对待,基于这个特性实现函数的高级应用。
- 【值】就是 JavaScript 中的数据,如数值、字符串、布尔、对象等。
<script>
function f1(callback) {
callback();
}
function f2() {
console.log("我就是高阶函数");
}
f1(f2);// f2 当成是一个普通的参数来使用(形参来使用)
setInterval(f2,1000);// 把f2 当成是一个普通参数 传递给别人使用
const btn=document.querySelector("button");
btn.addEventListener("click",f2);// f2 也是高阶函数
function getIndex() {
let index=0;
return function () {
index++;
console.log(index);
}
}
const ff=getIndex();
ff();
</script>
作用:后期 react阶段 会用到。 暂时做了解 后期会再讲解!!!
重绘和回流(重排)
-
回流(重排) 当 Render Tree 中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或全部文档的过程称为 回流。
-
重绘 由于节点(元素)的样式的改变并不影响它在文档流中的位置和文档布局时(比如:color、background-color、outline等), 称为重绘。
-
重绘不一定引起回流,而回流一定会引起重绘。
-
会导致回流(重排)的操作: 1.页面的首次刷新 2.浏览器的窗口大小发生改变 3.元素的大小或位置发生改变 4.改变字体的大小 5.内容的变化(如:input框的输入,图片的大小) 6.激活css伪类 (如::hover) 7.脚本操作DOM(添加或者删除可见的DOM元素)
-
简单理解影响到布局了,就会有回流
定义:出现重绘,不会重排;出现重排, 一定会出现重绘。
时间绑定-取消绑定
removeEventListener 可以取消元素的绑定事件。
<style>
body {
height: 100vw;
}
</style>
</head>
<body>
<script>
function text() {
console.log('gugu');
}
function text2() {
console.log(text);
}
//给body添加绑定事件
document.body.addEventListener('click',text)
//绑定多个同名事件
document.body.addEventListener('click',text2)
setInterval(function () {
//设置延时器 一定时间后取消该点击事件
document.body.removeEventListener('click',text)
},5000)
/*
1 addEventListener 可以绑定多个同名事件
2 removeEventListener 可以取消对应的事件类型和事件处理函数
3 无法取消 addEventListener 事件 对应的匿名函数
*/
</script>
</body>
注: 匿名函数无法取消绑定,应为对应的函数名不知道是什么,多以取消不了。
事件流动
时间流动实际上有三个阶段
1.最重要的 冒泡阶段
2.捕获阶段
3.目标阶段 (了解)-- 点击了最底层的标签 处在目标阶段。
字符串方法
| 字符串转换方法 | |
|---|---|
| 转大写 | toUpperCase() |
| 转小写 | toLowerCase() |
| 转数组 | str.split('') 括号内填写以"什么"为分割符 |
| 拼接字符串 | concat --很少用 直接用+拼接 |
<script>
// 我们在实际开发过程中,有很多需求要针对字符串做处理
// js 帮我们封装了很多大量和实用 字符串方法
// 先介绍一些
/* let str = 'abcdefg'
//转大写
console.log(str.toUpperCase()); */
/* let str = 'ABCDEFG'
//转小写
console.log(str.toLowerCase()); */
let str = 'abcdefg'
// 转数组
console.log(str.split('')); //=> ["a","b","c","d","e","f","g"]
let str1 = 'a-b-c-d-e-f-g'
console.log(str1.split('-'));//=> ["a","b","c","d","e","f","g"]
/*
1 转大写 toUpperCase()
2 转小写 toLowerCase()
3 转数组 str.split('') 按照什么来分割你的字符串变成数组
*/
</script>
数组方法
| 数组转换方法 | |
|---|---|
| 数组转字符串 | join('') |
| 数组拼接 | concat--- arr1.concat(arr2) 可拼接多个数组 |
<script>
const arr = ['a','b','c','d']
//数组转字符串 join('')
console.log(arr.join('')); //转后无分隔
console.log(arr.join('-')); //转后-分隔
//两个数组合并成一个数组 要合并的数组1.concat(要合并的数组2) --转换后数组1在前--
//可以拼接多个数组
const arr1 = [1,2,3,4]
const arr2 = ['a','b','c','d']
const arr3 = ['1','2','3','4']
console.log(arr2.concat(arr1)); //['a','b','c','d',1,2,3,4]
console.log(arr2.concat(arr1).concat(arr3)); // => ['a','b','c','d',1,2,3,4,'1', '2', '3', '4']
</script>
正则表达式
- 正则表达式(Regular Expression)是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象
- 通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式。
- 正则表达式在 JavaScript中的使用场景:
- 例如验证表单:用户名表单只能输入英文字母、数字或者下划线, 昵称输入框中可以输入中文(匹配) 2.比如用户名: /^[a-z0-9_-]{3,16}$/ 3.过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等 。
例:
<script>
/*
正则的作用 寻找字符串 检测 这个字符串这有没有我想要的文字
*/
const text = '学习正则表达式概念及语法,编写简单的正则表达式实现字符的查找或检测。'
//定义规则
const reg = /正则/
const reg1 = /六一/
/* const re = reg.test(text)
console.log(re); */
// 规则和字符串 匹配 test // 规则名.test(要检测的数据)
//有的话 返回true 没有返回 false
console.log(reg.test(text)); // => true
console.log(reg1.test(text)); // => false
</script>
元字符
- 普通字符: 大多数的字符仅能够描述它们本身,这些字符称作普通字符,例如所有的字母和数字。也就是说普通字符只能够匹配字符串中与它们相同的字符。
- 元字符(特殊字符) 是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能。 比如,规定用户只能输入英文26个英文字母,普通字符的话 abcdefghijklm….. 但是换成元字符写法: [a-z]
- 参考文档: MDN:developer.mozilla.org/zh-CN/docs/… 正则测试工具: tool.oschina.net/regex
1.边界符
表示位置,开头和结尾,必须用什么开头,用什么结尾
正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符
正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符
如果 ^ 和 $ 在一起,表示必须是精确匹配。
例1:
例2:
<script>
const text = '大聪明'
//边界符 /开头^ 结尾$/
//如果只加了^开头,那只要最前面和符号里一样就行,后面有多少字都会返回 true
const reg1 = /^大聪明/
const reg2 = /^大/
console.log(reg1.test(text)); // =>true
console.log(reg2.test(text)); // =>true
//如果只加了$结尾,那只要最后面的字和符号里一样就行,前面面有多少字都会返回true
const reg3 = /明$/
const reg4 = /聪明$/
const reg5 = /大聪明$/
console.log(reg3.test(text)); // =>true
console.log(reg4.test(text)); // =>true
console.log(reg5.test(text)); // =>true
//边界^$,那里面的文字必须和边界符一模一样,否则返回false,多一个字都不行
const reg6 = /^大明$/
const reg7 = /^大聪明$/
console.log(reg6.test(text)); // =>false
console.log(reg7.test(text)); // =>true
</script>
2.量词
量词用来 设定某个模式出现的次数
注意: 逗号左右两侧千万不要出现空格
<script>
// const str="路飞";
// const reg=/路飞/;
// console.log(reg.test(str));
// * 表示 放在它前面那一个字符 可以出现0次或者多次
// /^路*$/ => "", 路,路路,路路路
// console.log(/^千*$/.test('')); // true
// console.log(/^千*$/.test('千')); // true
// console.log(/^千*$/.test('千千')); // true
// console.log(/^千*$/.test('千千千')); // true
// + 表示 放在它前面那一个字符 可以出现1次或者多次
// console.log(/^千+$/.test(''));
// console.log(/^千+$/.test('千'));
// console.log(/^千+$/.test('千千'));
// console.log(/^千+$/.test('千千千'));
// ? 表示出现0次或者1次
// console.log(/^千?$/.test(''));// true
// console.log(/^千?$/.test('千')); // true
// console.log(/^千?$/.test('千千')); // false
// console.log(/^千?$/.test('千千千')); // false
// {n} 放在它前面的那一个字符 出现n次
// console.log(/^千{2}$/.test('')); // false
// console.log(/^千{2}$/.test('千')); // false
// console.log(/^千{2}$/.test('千千')); // true
// console.log(/^千{2}$/.test('千千千')); // false
// {n,} 放在它前面的字符 最少出现n次
// console.log(/^千{2,}$/.test('')); // true
// console.log(/^千{2,}$/.test('千')); // true
// console.log(/^千{2,}$/.test('千千'));// true
// console.log(/^千{2,}$/.test('千千千')); // true
// {n,m} 放在它前面的字符 最少出现n次,最大是m次
console.log(/^千{0,2}$/.test('')); // true
console.log(/^千{0,2}$/.test('千')); // true
console.log(/^千{0,2}$/.test('千千')); // true
console.log(/^千{0,2}$/.test('千千千')); // false
</script>
3.字符类
(一)[ ] 匹配字符集合
[ ] 里面加上 - 连字符
- 使用连字符 - 表示一个范围
- 如:
[a-z] 表示 a 到 z 26个英文字母都可以 [a-zA-Z] 表示大小写都可以 [0-9] 表示 0~9 的数字都可以
[ ] 里面加上 ^ 取反符号
- 比如: [ ^a-z ]匹配除了小写字母以外的字符 注意要写到中括号里面
<script>
// [ab] => 可以匹配 a 或者 b
// console.log(/[ab]/.test('abc1A'));// true
// console.log(/[ab]/.test('b'));// true
// console.log(/[abc]/.test('c'));// true
// 表示 a-z 任意的一个字母
// console.log(/[a-z]/.test('c'));// true
// console.log(/[a-z]/.test('d'));// true
// console.log(/[a-z]/.test('123'));// false
// console.log(/[a-d]/.test('a'));// true
// console.log(/[a-d]/.test('g'));// false
// 0-9 任意的一个数字
// console.log( /[0-9]/.test("1") );// true
// console.log( /[0-9]/.test("2") );// true
// console.log( /[0-9]/.test("0") );// true
// A-Z
// console.log(/[A-Z]/.test("a"));// false
// console.log(/[A-Z]/.test("B"));// true
// 同时满足 0-9a-zA-Z
/* console.log(/[0-9a-zA-Z]/.test('1'));// true
console.log(/[0-9a-zA-Z]/.test('a'));// true
console.log(/[0-9a-zA-Z]/.test('A'));// true
console.log(/[0-9a-zA-Z]/.test(' '));// false */
</script>
(二) . 匹配除换行符之外的任何单个字符
<script>
// . 表示除了(换行符tab之外)任意字符
// console.log(/路/.test('飞')); // false
// console.log(/./.test('飞')); // true
// console.log(/路.飞/.test('路大飞')); // true
// console.log(/路.飞/.test('路小飞')); // true
// console.log(/路.飞/.test('路中飞')); // true
// console.log(/路.飞/.test('路不飞')); // true
// console.log(/路.飞/.test('路 飞')); // false
// console.log(/路.飞/.test('路飞')); // false
// console.log(/路.飞/.test('路 飞')); // true
// \d 表示数字
// console.log(/\d/.test("路飞"));// false
// console.log(/\d/.test("1路飞"));// true
// console.log(/\d/.test("路3飞"));// true
// \D 不是数字之外的任意1个字符
// console.log(/\D/.test("123"));// false
// console.log(/\D/.test("12a3"));// true
// console.log(/\D/.test("12a3"));// true
// \w 字母、数字、下划线
// console.log(/\w/.test("123"));// true
// console.log(/\w/.test("%%"));// false
// console.log(/\w/.test("%1%"));// true
// console.log(/\w/.test("%a%"));// true
// console.log(/\w/.test("%_%"));// true
// \W 除去了 字母 、数字、下划线 之外字符
// console.log(/\W/.test("123"));// false
// console.log(/\W/.test("1%23"));// true
// \s 匹配空格
// console.log(/\s/.test("123"));// false
// console.log(/\s/.test("1 23"));// true
// \S 除了空格之外的字符
// console.log(/\S/.test('1 23'));// true
// console.log(/\S/.test('1 2 '));// false
// console.log(/\S/.test(' '));// false
</script>
(三) 预定义:指的是某些常见模式的简写方式。
<script>
//日期格式
console.log(/^\d{4}-\d{1,2}-\d{1,2}/.test('2020-04-27'));
</script>
测试正则案例
用户名/手机号/邮箱
<script>
//注册账号 用户名/手机号/邮箱
//用户名规则--- 必须是字母,范围3-8
const username = 'guliuyi'
//设置用户名规则
const nameRule = /^[a-zA-Z]{3,8}$/
//要加上开始和结束边界符,如果不加 开头和结尾以其他符号开头也会返回true
console.log(nameRule.test(username));
//手机号规则 以数字1开头 第二个数字可以是35789 其他9位数字 (一共11个数字)
const tel = '15625883210'
//设置手机号规则
const telRule = /^1[35789]\d{9}$/
//同样要加上开始和结束边界符
console.log(telRule.test(tel));
//邮箱规则
// 邮箱名称 可以是字母或者数字 最少要有一个 {1,} 或者 + //+表示至少出现一次
// 固定的分隔符 @
// 字母或者数字
// 匹配一个. => \. (要识别.本身 .前面务必加\ 否则.会被识别为除换行符外的任意一个符号)
// 规定 com cn
const mail = 'gugu123@liuyi.com'
const mailRule = /^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.c(om|n)$/
console.log(mailRule.test(mail));
</script>