本地存储
本地存储特性:
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。 1、数据存储在用户浏览器中。 2、设置、读取方便、甚至页面刷新不丢失数据。 3、容量较大,sessionStorage和localStorage约 5M 左右。
localStorage
-
生命周期永久生效,除非手动删除 否则关闭页面也会存在。
-
可以多窗口(页面)共享(同一浏览器可以共享)。
-
以键值对的形式存储使用。
本地存储:
localStorage.setItem("要存储的元素",值)
获取数据:
localStorage.getItem("存储的元素")
删除数据:
localStorage.removeItem("要删除的元素")
清空所有数据:
localStorage.clear();
注意:
-
存储完的值,无论他原来是什么类型, 获取过来 返回都是字符串类型。
-
本地存储 存复杂类型数据 如:对象数据和数组, 会导致数据丢失;他有固定规则,只能存简单类型的数据。
-
想存储对象和数组的话 ,可以用JSON.stringify(要转换的元素),快速帮我们把对象和数组解析存储;再重新用JSON.parse(自定义名字),把他转换成数组,可以取出时使用。
语法:
localStorage.setItem("要存储的元素",值); let 自定义名字 = JSON.stringify(要转换的元素); //再转换成数组 JSON.parse(自定义名字);
页面自动换肤-存储数据案例
<body>
//input type="color" 有兼容性问题,比较少用,像ie都使用不了
<input type="color">
<script>
let input = document.querySelector("input");
//把刷新后的状态有背景颜色=上一次存储的背景颜色 放在触发事件外面
document.body.style.backgroundColor = localStorage.getItem("input")
//input 选择完毕时触发事件
input.addEventListener("change", function () {
//让背景颜色= input.value会显示#xxxxxx 你在input选择的颜色
document.body.style.backgroundColor = input.value;
//存储数据
localStorage.setItem("input", this.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>学生就业薪资-本地存储版本-同学自己去补充</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 定义数组 负责存放表格要显示的数据
// 获取本地存储中的数组(字符串格式) 转成 数组格式
// 第一次打开页面的时候 ,本地存储里面会有数据吗
//如果数据不存在 会显示null
const strArr= localStorage.getItem("arr");
let arr = [];
if(strArr){
// 有值 转成数组
arr = JSON.parse(strArr);
} else{
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 会一直保存着,除非手动删除。
<script>
//sessionStorage 本地存储的用法和 localStorage 是一样的。
//只是他存储的数据 在关闭页面后 ,数据就会丢失
// localStorage 会一直保存,除非手动删除。
//存储的内容 在 会话存储空间
//存数据
sessionStorage.setItem("ss",123);
//取数据
sessionStorage.getItem("ss");
//删除一个数据
sessionStorage.removeItem("ss");
//清空所有数据
sessionStorage.clear();
</script>
补充知识点
dom元素属性
标签的属性有 两种:
- 固有属性 比如: id , href , src ,获取和设置比较方便,可以直接使用点语法。
<body>
<a href="#" id="333"></a>
<script>
// 标签的属性有 两种:
// 1.固有属性 比如: id , href , src ,获取和设置比较方便,可以直接使用点语法。
let a = document.querySelector("a");
// 获取固有属性
console.log(a.id)
console.log(a.href)
//直接修改
a.id="111"
console.log(a.id)
</script>
</body>
自定义属性
2.自定义属性
是自己给标签创建的属性名。
- 自定义属性 不能直接通过点语法来获取和设置。
- 获取 getAttribute ("自定义的属性名");
- 设置修改 setAttribute ("自定义的属性名",“修改的内容”);
- 删除掉属性 removeAttribute ("要删除的属性名")
<body>
<a href="#" id="333" hello="你好"></a>
<script>
//自定义属性 不能直接通过点语法来获取和设置
//获取 getAttribute("自定义的属性名")
console.log(a.getAttribute("hello"))
//设置修改 setAttribute("自定义的属性名",“修改的内容”)
a.setAttribute("hello","再见")
//删除掉属性 removeAttribute("要删除的属性名")
a.removeAttribute("hello")
</script>
</body>
h5 建议的自定义属性
h5建议的 自定义属性:
写法:
属性的时候 : 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>
小结:
标签的属性 有两种分为
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>
高阶函数
这个函数可以把另一个函数当成参数来接收处理,或者返回另外一个新的函数。
作用:后期 react阶段 会用到。
示例:
<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>
浏览器渲染页面的流程(了解)
1.重排:主要 修改了元素的大小,位置,定位+浮动
会损耗浏览器的性能。
2.重绘: 主要修改; 像修改外观颜色字体颜色这些,性能损耗比较低。
3.最理想的情况: 不要出现重排重绘。
4.定义:出现重绘,不会重排;出现重排, 一定会出现重绘。
事件绑定-取消绑定
removeEventListener 可以取消元素的绑定事件。
写法:
removeEventListener(“触发事件”,要取消的对应函数名)
注意:
- 匿名函数无法取消绑定 ,因为对应的函数名不知道是什么,所有取消不了。
示例:
<body>
<button>点击</button>
<script>
function func(){
console.log('123456789')
}
function func2(){
console.log("hhh")
}
let btn = document.querySelector("button");
//给按钮绑定 点击执行func函数里的打印
//addEventListener 可以绑定多个同名事件
btn.addEventListener("click",func);
btn.addEventListener("click",func2);
//加个延时器 5秒后执行
//取消掉输出hhh的点击事件 removeEventListener(“触发事件”,要取消的对应函数名)
setTimeout(function() {
btn.removeEventListener("click",func2)
}, 5000);
// 注意: 匿名函数无法取消绑定 ,因为对应的函数名不知道是什么,所有取消不了
</script>
</body>
事件流动
事件流动 实际上 有3个阶段:
1.最重要的 冒泡阶段
2.捕获阶段
3.目标阶段 (了解)
目标阶段
点击了最底层的标签 处在目标阶段。
字符串的方法
| 字符串转换的方法 | |
|---|---|
| toUpperCase() | 大写转小写 |
| toLowerCase() | 小写转大写 |
| str.split('') | 字符串转数组 |
<script>
//实际开发过程中 有很多需求要针对字符串做处理
//js 帮我们封装了很多大量和实用的 字符串方法
//先介绍一些
let msg = "hello"
let msg2 = "AABBCC"
//大写转小写 toUpperCase()
console.log(msg.toUpperCase()) ;
//小写转大写 toLowerCase()
console.log(msg2.toLowerCase()) ;
//字符串转数组 str.split('')
let str ="abcdefg" //想要变成数组["a","b","c","d","e","f","g"]
console.log(str.split(''));
let str2 ="a-b-c-d-e-f-g" //想要变成数组["a","b","c","d","e","f","g"]
console.log(str2.split('-'));
</script>
数组方法
| 数组转换的方法 | |
|---|---|
| join("") | 数组转字符串 |
| 要合并的数组1.concat(要合并的数组2) | 两个数组连接起来 |
<script>
//数组 补充常用方法
//数组转字符串 join("")
const arr = ["a","b","c","d",]
const arr2 = ["a","b","c","d",]
console.log(arr.join("")) //打印显示 abcd 字符串
console.log(arr2.join("-")) //打印显示 a-b-c-d 字符串
//数组和数组之间连接 要合并的数组1.concat(要合并的数组2)
let arr3 =[1,2,3,4]
const arr4 = ["a","b","c","d",]
//将两个数组合并成一个数组
console.log(arr3.concat(arr4));
//打印显示[1,2,3,4,"a","b","c","d"]
</script>
正则表达式
- 正则表达式(Regular Expression)是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象
- 通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式。
正则表达式在 JavaScript中的使用场景:
- 例如验证表单:用户名表单只能输入英文字母、数字或者下划线, 昵称输入框中可以输入中文(匹配)。
- 比如用户名: /^[a-z0-9_-]{3,16}$/
- 过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等 。
语法:
JavaScript 中定义正则表达式的语法有两种,先学习其中比较简单的方法:
示例:
<script>
/*
正则的作用: 寻找字符串 检测 这个字符串有没有我想要的文字
*/
//判断这个字符串有没有 梦想 两个字
const str = `斤斤计较经济界梦想哈哈哈哈`
//定义规则
const reg = /梦想/;
//规则和字符串 匹配 用 自己定义的规则名.test(要检测的字符串) 检测
console.log(reg.test(str)); //有的话 返回true 没有返回 false
</script>
元字符
-
普通字符: 大多数的字符仅能够描述它们本身,这些字符称作普通字符,例如所有的字母和数字。也就是说普通字符只能够匹配字符串中与它们相同的字符。
-
元字符(特殊字符):
-
是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能。
-
比如,规定用户只能输入英文26个英文字母,普通字符的话 abcdefghijklm….. 但是换成元字符写法: [a-z]
-
-
参考文档:
边界符
边界符(表示位置,开头和结尾,必须用什么开头,用什么结尾)。
正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符:
如果 ^ 和 $ 在一起,表示必须是精确匹配。
示例:
<script>
const str = `来得分哈`
//边界符 /^$/
//边界^$,那里面的文字必须和边界符一模一样,否则返回false,多一个字都不行
const reg = /^来得分哈$/;
//如果只加了^开头,那只要最前面和符号里一样就行,后面有多少字都会返回 true
const reg = /^来/;
//如果只加了$结尾,那只要最后面的字和符号里一样就行,前面面有多少字都会返回true
const reg = /分哈$/;
//规则和字符串 匹配
console.log(reg.test(str));
</script>
量词
量词用来 设定某个模式出现的次数。
注意: 逗号左右两侧千万不要出现空格。
示例:
<body>
<script>
/* const str ="小文"
const reg=/小文/;
console.log(reg.test(str)); */
//以上几行代码 可以简写:
console.log(/小文/.test("小文"));
//* 表示放在他前面的那一个字符 可以出现0次或者多次
// console.log(/^文*$/.test("")); //true
// console.log(/^文*$/.test("文")); //true
// console.log(/^文*$/.test("文文")); //true
// console.log(/^文*$/.test("文文文")); //true
//+ 表示放在他前面的那一个字符 可以出现1次或者多次
// console.log(/^文+$/.test("")); //false
// console.log(/^文+$/.test("文")); //true
// console.log(/^文+$/.test("文文")); //true
// console.log(/^文+$/.test("文文文")); //true
//? 表示放在他前面的那一个字符 可以出现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("")); //false
// console.log(/^文{2,}$/.test("文")); //false
// console.log(/^文{2,}$/.test("文文")); //true
// console.log(/^文{2,}$/.test("文文文")); //true
// {n,m} 放在它前面的那一个字符 最少出现n次,最大是m次
console.log(/^文{2,3}$/.test("")); //false
console.log(/^文{2,3}$/.test("文")); //false
console.log(/^文{2,3}$/.test("文文")); //true
console.log(/^文{2,3}$/.test("文文文")); //true
</script>
</body>
字符类
预定义:指的是某些常见模式的简写方式。
<body>
<script>
// . 表示除了(换行符之外)任意字符
// 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
// \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('123'));// true
// console.log(/\S/.test(' '));// false
// console.log(/\S/.test(' '));// false
</script>
</body>
<script>
//[ab] =>可以匹配 a 或者 b
// console.log(/[ab]/.test("a")); //true
// console.log(/[ab]/.test("b")); //true
// console.log(/[abc]/.test("c")); //true
//[a-z] 表示a-z里的任意一个
// console.log(/[a-z]/.test("a")); //true
// console.log(/[a-z]/.test("b")); //true
// console.log(/[a-d]/.test("f")); //false
// console.log(/[a-d]/.test("123")); //false
//[0-9] 0-9任意的一个数字
// console.log(/[0-9]/.test("0")); //true
// console.log(/[0-9]/.test("2")); //true
// console.log(/[0-9]/.test("9")); //true
// console.log(/[0-100]/.test("99")); //false 因为是字符串的原因这个只适用个位数的
// A-Z 表示大写的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>
//要求注册账户名 必须只能是字母,且长度大于3-8
console.log(/[a-zA-Z]{3,8}/.test("111AaA2323594")) //这样还是显示true,所以是错的。因为这样的意思是只要字符串里有3个及以上的字母然后字母个数在3-8就会给true,所以要加上边界符。
// 所以 需要把量词 边界符和字符结合使用 可以实现。
console.log(/^[a-zA-Z]{3,8}$/.test("aasagdfi")) // true 这样就完成以上要求了
//手机号码验证
//规则 以数字1开头 第二个数字可以是35789 其他9位数字 (一共11个数字)
console.log(/^1[35789]\d{9}$/.test("15123456789")) //true
//console.log(/^1[35789]\d{9}$/.test("135789123456789")) //false
//console.log(/^1[35789]\d{9}$/.test("12123456789")) //false
//邮箱名称
//规则
// 1.前面可以是字母或者数字,最少要有一个{1,} 或者 +
//2.固定的分隔符 @
// 3.字母或者数字 也是最少要有1个 {1,} 或者 +
//4. 一个固定的. (注意直接写.的话是指除换行符外的任意一个符号) 要表示 . 本身 前面加个\就行 写法是 \.
//5. 最后是com或者cn 写法是 c(om|n)
console.log(/^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.c(om|n)$/.test("6@2.cn")) //true
console.log(/^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.c(om|n)$/.test("6@2.com")) //true
</script>