项目 1 点击切换效果
首次使用 JS 实现点击切换效果(代替 CSS)
-
传统基于操作 DOM 方式实现需求的步骤
-
想操作哪个元素,就先获取哪个元素
-
给某元素绑定某事件,什么时候干什么事,叫做事件绑定,点击的时候干什么,就要给元素点击的时候,绑定要做的事
-
在事件触发的时候修改元素的样式等
-
两大思想:操作 DOM(传统 JS 和 JQuery) 操作数据
VUE 和 REACT 思想: 操作数据
第一步准备视图
第二步准备数据
第三步建立视图与数据的关系
<!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;
list-style: none;
}
.box {
width: 400px;
margin: 30px auto;
cursor: pointer;
z-index: 99;
}
.box>p{
box-sizing: border-box;
width: 100px;
height: 50px;
line-height: 50px;
text-align: center;
border: 1px solid lightcoral;
}
.detail{
background-color: #fff;
box-sizing: border-box;
height: 50px;
line-height: 50px;
text-align: center;
border: 1px solid lightcoral;
z-index: -1;
height: 300px;
line-height: 300px;
display: none;
margin-top: -1px;
}
</style>
</head>
<body>
<div class="box" id="box">
<p id="p">购物车</p>
<div class="detail" id="detail">
购物车相关信息
</div>
</div>
<script>
// ======================IMPORT JS========================
// 第一步 获取元素并存储
// document.getElementById([ID]):在整个文档中,通过元素的 ID 获取当前这个元素对象
let box = document.getElementById('box');
let detail = document.getElementById('detail');
// 第二步 事件绑定
// 元素对象.事件 = 方法
// 元素对象.onxxx = function(){} : 事件绑定,xxx 事件类型(click/mouseover/mousedown/keydown...)
// 点击,触发事件,执行方法
box.onclick = function(){
// 第三步 触发事件后调用的方法,此处为修改元素某一个样式值
// 元素对象.style.xxx = xxx : 修改元素某一个样式值
// 这种当时操作的是元素行内样式
detail.style.display = 'block';
}
</script>
</body>
</html>
目前这种方法操作的是修改元素行内样式
点击前
点击后
进阶: 点一下显示,点一下又隐藏,所以要增加一个判断来判断当前状况
<!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;
list-style: none;
}
.box {
width: 400px;
margin: 30px auto;
cursor: pointer;
z-index: 99;
}
.box>p{
box-sizing: border-box;
width: 100px;
height: 50px;
line-height: 50px;
text-align: center;
border: 1px solid lightcoral;
}
.detail{
background-color: #fff;
box-sizing: border-box;
height: 50px;
line-height: 50px;
text-align: center;
border: 1px solid lightcoral;
z-index: -1;
height: 300px;
line-height: 300px;
margin-top: -1px;
/* 去掉了 display */
}
</style>
</head>
<body>
<div class="box" id="box">
<p id="p">购物车</p>
<!-- 修改这里了 -->
<div class="detail" id="detail" style="display: none;">
购物车相关信息
</div>
</div>
<script>
// ======================IMPORT JS========================
// 第一步 获取元素并存储
// document.getElementById([ID]):在整个文档中,通过元素的 ID 获取当前这个元素对象
let box = document.getElementById('box');
let detail = document.getElementById('detail');
// 第二步 事件绑定
// 元素对象.事件 = 方法
// 元素对象.onxxx = function(){} : 事件绑定,xxx 事件类型(click/mouseover/mousedown/keydown...)
// 点击,触发事件,执行方法
box.onclick = function(){
// 第三步 触发事件后调用的方法,此处为修改元素某一个样式值
// 元素对象.style.xxx = xxx : 修改元素某一个样式值
// 这种操作的是元素行内样式,如果我们没有把样式写在行内上,在 JS 中基于.style.xxx 的方式是无法获取到样式的[获取方法在后续讲]
// 1.首先获取detail原有的样式(显示还是隐藏) : 元素.style.xxx 就是获取行内样式(不写 = xxx 就是获取 写 = xxx 就是赋值)
// 前提是需要在元素行内设置这个样式才能获取到
let n = detail.style.display ;
if( n == 'none'){
// 2.判断
// 当前是隐藏的,我们让其显示
detail.style.display = 'block';
} else{
// 当前是显示的,我们让其隐藏
detail.style.display = 'none';
}
}
</script>
</body>
</html>
简洁版 JS
<script>
// 基于 id 可以不获取直接使用
// let box = document.getElementById('box');
// let detail = document.getElementById('detail');
box.onclick = function(){
let n = detail.style.display;
if(n === 'none'){
detail.style.display = 'block';
}else{
detail.style.display = 'none';
}
}
</script>
项目 2 判断逻辑的案例训练 (判断数字正负)
需求: 判断一个数字是正数负数
实现效果:
<body>
<input type="text" id="numInp">
<button id="submit">计算结果</button>
<!-- IMPORT JS -->
<script>
// 第一步 获取元素 想操作谁就先获取谁
let numInp = document.getElementById('numInp');
let submit = document.getElementById('submit');
// 第二步 事件绑定 谁触发事件就绑给谁
submit.onclick = function () {
// 第三步 行为
// 1.获取文本框中的内容: 元素.value
let n = numInp.value;
// 2. 获取的结果是字符串,需要转换为数字
n = Number(n);
// 3. 验证是否为有效数字
if (!isNaN(n)) {
// 有效数字 进入
//4. 接下来根据输入的内容进行相关验证.输出对应的结果
if (n > 0) {
console.log('输入的是正数');
} else if (n < 0) {
console.log('输入的是负数');
} else {
console.log('当前输入的是零');
}
} else {
console.log('当前输入的是非法数字');
}
}
</script>
</body>
项目 3 奇偶行变色(隔行变色) 仅用作练习JS
1. 隔行变色
<!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>隔行变色</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
#newsBox {
margin: 20px auto;
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 2px solid lightblue;
}
#newsBox li {
line-height: 35px;
border-bottom: 1px dashed lightcoral;
}
#newsBox li:nth-last-child(1) {
border-bottom: none;
}
/* 基于 CSS 实现 */
/* #newsBox li:nth-child(even){
background-color: lightgray;
}
#newsBox li:hover{
background-color: #bfa;
} */
</style>
</head>
<body>
<!-- ul#newsBox>li*5{我是第$个li} -->
<div id="newsBox">
<li>我是第1个</li>
<li>我是第2个</li>
<li>我是第3个</li>
<li>我是第4个</li>
<li>我是第5个</li>
</div>
<!-- IMPORT JS -->
<script>
// 第一步 获取元素
let newsBox = document.getElementById('newsBox');
// [context].getElementsByTagName([tagname]):在指定的 context 范围之内,通过标签名获取一组元素(也叫元素集合 HTMLCollection)
// 元素集合和数组很相似,也是一数字索引作为属性名,有 length 属性存储长度,但是不是数组,属于'类数组'
let newsList = newsBox.getElementsByTagName('li');
console.dir(newsList); // 见图 1-1
// 第二步 判断是奇数行还是偶数行,然后确定颜色
// 因为要重复判断,所以循环
// 循环所有获取的 li,判断每一个 li 的奇偶行让其有不同背景颜色
//循环
for (let i = 0; i < newsList.length; i++) {
// 第一轮 i = 0 操作第一个 li newsList[0]
// 第二轮 i = 1 操作第一个 li newsList[1]
// 第三轮 i = 2 操作第一个 li newsList[2] ...
// => newsList[i] 当前本轮循环我们要操作的这个li
let curLi = newsList[i]
// 判断
// i=0(索引偶数) 第一个 li 是奇数行
// i=1(索引奇数) 第二个 li 是奇数行
// => 当前索引是偶数,则这个 li 是奇数行,否则是偶数行
// 偶数判断标准: 能被 2 整除(除以 2 余数为 0) n%2 == 0 为 true
if (i % 2 === 0) {
// 索引是偶数,代表奇数行
curLi.style.backgroundColor = '#BFA';
} else {
// 索引是奇数,代表偶数行
curLi.style.backgroundColor = '#DDD';
}
}
</script>
</body>
</html>
图 1-1
-
[context].getElementsByTagName([tagname]):在指定的 context 范围之内,通过标签名获取一组元素(元素集合 HTMLCollection)
-
元素集合和数组很相似,也是一数字索引作为属性名,有 length 属性存储长度,但是不是数组,属于'类数组'
效果:
简洁版代码
<script>
let newsBox = document.getElementById('newsBox');
let newsList = newsBox.getElementsByTagName('li');
console.dir(newsList);
for (let i = 0; i < newsList.length; i++) {
let curLi = newsList[i];
if (i % 2 === 0) {
curLi.style.backgroundColor = '#BFA';
} else {
curLi.style.backgroundColor = '#DDD';
}
}
</script>
// 更简洁高级的三元运算符
for (let i = 0; i < newsList.length; i++) {
let curLi = newsList[i];
curLi.style.backgroundColor = i % 2 === 0 ? '#BFA' : '#DDD';
2. 鼠标滑过变色
-
var 和 let 的区别后续补充
-
this : 在事件绑定方法中 this 代表当前操作元素 .还有很多其他情况
let newsBox = document.getElementById('newsBox');
let newsList = newsBox.getElementsByTagName('li');
// 1.实现奇偶行变色
for (let i = 0; i < newsList.length; i++) {
let curLi = newsList[i]
curLi.style.backgroundColor = i % 2 === 0 ? '#DDD' : '#BFA' ;
let origin = curLi.style.backgroundColor
// 2. 循环的时候给每个 LI 绑定 mouseover/mouseout 事件
curLi.onmouseover = function(){
// this : 当前操作的这个 li
this.style.backgroundColor = 'lightblue';
}
curLi.onmouseout = function(){
// 鼠标离开恢复到当前颜色
// 思考题 如何知道当前的原色? 有很多种方法
this.style.backgroundColor = origin;
}
}
3. 鼠标滑入变色滑出恢复 - 自定义属性
自定义属性编程思想:
前期把一些值存储到元素的自定义属性上,后期需要用到的时候,直接从属性上获取这些值即可.
<!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>隔行变色</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
#box {
margin: 10px auto;
box-sizing: border-box;
width: 500px;
}
#box li {
line-height: 50px;
border-bottom: 1px dashed rgb(250, 118, 118);
}
#newsBox li:nth-last-child(1) {
border-bottom: none;
}
</style>
</head>
<body>
<div id="box">
<li>我是第1个</li>
<li>我是第2个</li>
<li>我是第3个</li>
<li>我是第4个</li>
<li>我是第5个</li>
</div>
<!-- IMPORT JS -->
<script>
var box = document.getElementById('box');
var boxList = box.getElementsByTagName('li');
// 1.实现奇偶行变色
for (var i = 0; i < boxList.length; i++) {
// boxList[i] 当前循环要操作的li
boxList[i].style.backgroundColor = i % 2 === 0 ? '#DDD' : '#BFA' ;
// 设置自定义属性来存储每一个LI的背景颜色
boxList[i].myorigin = boxList[i].style.backgroundColor;
// 2. 循环的时候给每个 LI 绑定 mouseover/mouseout 事件
boxList[i].onmouseover = function(){
// this : 当前操作的这个 li
this.style.backgroundColor = 'lightblue';
}
boxList[i].onmouseout = function(){
// 鼠标离开恢复到当前颜色
// 自定义属性
this.style.backgroundColor = this.myorigin;
}
}
</script>
</body>
</html>
boxList
理解元素对象与元素对象集合
摘自珠峰视频
项目 4 选项卡案例
需求:点击选项卡,页卡改变
第一次写 使用 var 效果未能实现
<!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;
list-style: none;
}
#tabBox {
box-sizing: border-box;
width: 500px;
margin: 20px auto;
}
#navBox {
display: flex;
position: relative;
top: 1px;
}
#navBox li {
box-sizing: border-box;
margin-right: 10px;
line-height: 35px;
padding: 0 10px;
border: 1px solid #999;
}
#navBox li.active {
border-bottom-color: #fff;
}
#tabBox>div {
display: none;
box-sizing: border-box;
padding: 10px;
height: 150px;
border: 1px solid #999;
}
#tabBox>div.active {
/* 加了空格就成后代选择器 就不是交集选择器*/
display: block;
}
</style>
</head>
<body>
<div id="tabBox">
<ul id="navBox">
<li class="active">编程</li>
<li>读书</li>
<li>运动</li>
</ul>
<div class="active">编程使我快乐</div>
<div>读书使我幸福</div>
<div>运动使我健康</div>
</div>
<!-- IMPORT JS -->
<script>
// 第一步 获取元素 操作谁就获取谁
var tabBox = document.getElementById('tabBox');
var tabList = tabBox.getElementsByTagName('div');
var navBox = document.getElementById('navBox');
var navList = navBox.getElementsByTagName('li');
// 第二步 循环三个 li,给每个 li 都绑定点击事件
for (var i = 0; i < navList.length; i++) {
// navList[i] : 当前循环下我们要操作的那个 li(i变量存储的值是我们需要获取指定元素的索引)
navList[i].onclick = function (){
console.log(i); //=> 3
changeTab(i);
}
}
// 封装函数 实现选项卡的切换
// clickIndex: 创建函数的时候,还不知道点的是谁,所以定义一个入口(存储点击这一项的索引),执行方法的时候把点击这一项的索引传递进来即可
function changeTab(clickIndex) {
// 1. 先让所有的 li 和 div 都没有选中的样式 => 重复 => 循环
for(var i = 0; i < navList.length; i++){
navList[i].className = '';
tabList[i].className = '';
}
// 2. 点击的是谁,就给谁加
navList[clickIndex].className = 'active';
tabList[clickIndex].className = 'active';
}
</script>
</body>
</html>
changeTab 函数有效
页面执行效果: 点击无效
原因: 点击每个 li 索引都显示为 3
解析:
只有 JS 代码加载完成才能看到页面,只有看到页面用户才能点击
加载到循环代码时 i=0 , i<3 , i++ ;
i=0 navList[0].onclick = function(){...} 绑定事件的时候方法没有执行,点击第一个 li 的时候它才执行. i++ =>1
i=1 navList[1].onclick = function(){...} 绑定事件的时候方法没有执行,点击第二个 li 的时候它才执行. i++ =>2
i=2 navList[2].onclick = function(){...} 绑定事件的时候方法没有执行,点击第三个 li 的时候它才执行. i++ =>3
3<3 不通过,循环结束 i 已经是 3 了
...页面加载完成,用户看到页面
用户点击某一个页卡,接下来开始执行绑定的方法,方法中遇到一个 i,但是此时 i 已经是循环结束后的 3 了.
所以报错
修正:
解决方案一 自定义属性解决办法
解决办法一: 自定义属性解决办法
for (var i = 0; i < navList.length; i++) {
// navList[i] : 当前循环下我们要操作的那个 li(i变量存储的值是我们需要获取指定元素的索引)
// 在循环给每一个 li 绑定点击事件的时候,给每一个 li(元素对象)设置一个自定义属性myIndex,属性值存储的是当前 li 的索引
navList[i].myIndex = i ;
navList[i].onclick = function (){
// 我想用的是点击这个 li 的索引,但是 i 不是
// this是当前点击的这个元素li,this.myIndex 获取的就是之前绑定在元素自定义属性上的索引值i
changeTab(i);
}
}
修改后的循环解读:
加载到循环代码时 i=0 , i<3 , i++ ;
i=0
navList[0].myIndex = [0]
navList[0].onclick = function(){...} i++ =>1
i=1
navList[1].myIndex = [1]
navList[1].onclick = function(){...} i++ =>2
...
解决方案二: 闭包
闭包 : 人为写一个闭包
for (var i = 0; i < navList.length; i++) {
navList[i].onclick = (function (i){
return function(){
changeTab(i);
}
})(i)
解决方案三:
ES6 中的 let 解决方案
let 也能实现闭包
for (let i = 0; i < navList.length; i++) {
navList[i].onclick = function (){
changeTab(i);
}
}
项目 5 点击实现页面改变颜色
写法一 使用 switch case
<!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>点击变颜色</title>
<style>
*{
margin: 0;
padding: 0;
list-style: none;
}
html,body{
height: 100%;
overflow: hidden;
}
button{
padding: 40px;
line-height: 10px;
}
</style>
</head>
<body style="background-color: white;">
<button id="changeBtn">点我变颜色 白红绿蓝白红...</button>
<!-- IMPORT JS -->
<script>
let body = document.body;
let changeBtn = document.getElementById('changeBtn');
changeBtn.onclick = function(){
// 首先获取当前的背景色
// 元素.style.xxx 只能获取行内样式
// 颜色在样式中使用 16 进制模式,JS 获取到的是 RGB 的值;写的是单词颜色,获取到的是单词
let bg = body.style.backgroundColor
// 判断背景色在不同情况下变不同颜色
switch (bg){
case 'white':
body.style.backgroundColor = 'red';
break;
case 'red':
body.style.backgroundColor = 'green';
break;
case 'green':
body.style.backgroundColor = 'blue';
break;
default:
body.style.backgroundColor = 'white';
}
}
</script>
</body>
</html>
写法二 更高级的写法 变换更多颜色 使用数组
-
更多颜色
-
不用担心颜色的格式是否是 RGB 等等
-
不用担心元素.style 只能获取和更改行内样式
-
避免冗余
<!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>点击变颜色</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
html,
body {
height: 100%;
overflow: hidden;
}
button {
padding: 40px;
line-height: 10px;
}
</style>
</head>
<body style="background-color: white;">
<button id="changeBtn">点我变色</button>
<!-- IMPORT JS -->
<script>
let body = document.body;
let changeBtn = document.getElementById('changeBtn');
let ary = ['white', 'red', 'yellow', 'orange', '#bfa', 'pink', 'yellowgreen', '#999'];
let i = 0;
// 从数组中拿值,只需 ary[数字索引]
//点击按钮实现功能
changeBtn.onclick = function () {
i++; // 每次点击,基于累加后的 i 作为索引,在数组中拿到不同的颜色样式值
// 边界判断 如果索引自增后大于数组最大索引,我们让其从 0 开始即可
i > ary.length - 1 ? i = 0 : null;
body.style.backgroundColor = ary[i];
}
</script>
</body>
</html>
开关灯案例
不适用 switch 加第三方值 state 做逻辑判断
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>开灯</button>
<button>关灯</button>
<h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
<h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
<h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
<h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
<h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
</body>
</html>
<script>
var btn1 = document.getElementsByTagName('button')[0];
var btn2 = document.getElementsByTagName('button')[1];
var body = document.getElementsByTagName('body')[0];
btn1.style.display = 'none';
btn1.onclick = function () {
btn1.style.display = 'none';
btn2.style.display = 'block';
body.style.color = 'black';
body.style.backgroundColor = 'white';
}
btn2.onclick = function () {
btn1.style.display = 'block';
btn2.style.display = 'none';
body.style.color = 'white'
body.style.backgroundColor = 'black'
}
// 事件都要用一个函数来包行为
// 事件的默认值都是 null
</script>
项目 6 点击弹出索引(4.选项卡案例) 自定义属性结合函数底层运行机制理解
是否能实现点击目标按钮就弹出对应按钮索引的效果 ?
如果不能,请说明原因并修改
<body>
<button value="按钮1">按钮1</button>
<button value="按钮2">按钮2</button>
<button value="按钮3">按钮3</button>
<button value="按钮4">按钮4</button>
<button value="按钮5">按钮5</button>
<script>
var btnList = document.getElementsByTagName('button');
for (let i = 0; i < btnList.length; i++) {
btnList[i].onclick = function () {
alert(i);
}
}
</script>
</body>
答: 不能,点击任何按钮都只会弹出'5' . 原因与项目4选项卡案例相同
图解要点:
- btnList获得的值是一个对象类型值(元素集合), 里面有五个botton,每个button各自也是对象.
- for循环 , i依次循环 , 到5为止
同时,分别给每个 按钮 btnList[i] 添加了 onclick 属性,属性值是函数 , 所以要另开辟五个堆内存 , 将函数体代码字符串存储起来.里面的i都是字符串 , 不是变量 .
- 点击第二个BUTTON : 把之前赋值给onclick属性对应的函数CCCFFF111执行 , 函数执行,开辟一个全新的私有栈内存.在自身找变量 , 没有, 去外边找, 得到 i = 5
解决 :
在循环开始后点击开始前给每个BUTTON 绑上各自的索引 , 让函数不用去找最外边的5 .
代码:
<body>
<button value="按钮1"></button>
<button value="按钮2"></button>
<button value="按钮3"></button>
<button value="按钮4"></button>
<button value="按钮5"></button>
<script>
var btnList = document.getElementsByTagName('button');
for (let i = 0; i < btnList.length; i++) {
btnlist[i].myIndex = i;
btnList[i].onclick = function () {
alert(this.myIndex);
}
}
</script>
</body>
项目 7 字符串方法项目
7.1 时间字符串的处理
方案一 : 一路REPLACE 利用REPLACE一次只替换一个字符的特性
let time = '2019-7-24 12:6:23';
// '2019年07月24日 12时06分23秒'
time = time.replace('-','年').replace('-','月').replace('','日 ').replace(':','时').replace(':','分')+'秒';
console.log(time); //=>'2019年7月24日 12时6分23秒'
方案二: 获取年月日时分秒这几个值后,再拼
获取值的方法: 基于split和正则拆分
let time = '2019-7-24 12:6:23';
let ary = time.split(/(?: |-|:)/g);
console.log(ary); // => (6) ['2019', '7', '24', '12', '6', '23']
拼接
time = ary[0]+'年'+ary[1]+'月'+ary[2]+'日'; // => 2019年7月24日
加上补零的方法
time = ary[0]+'年'+addZero(ary[1])+'月'+addZero(ary[2])+'日';
个位数设虚位补零方法:
let addZero = val => {
if(val.length < 2){
val = '0' + val
}
return val
}
简化:
let addZero = val => {
val = val.length < 2 ? '0' + val : val
return val
}
再简化:
let addZero = val => {
return val.length < 2 ? '0' + val : val
}
箭头函数return只有一行,则简化:
let addZero = val => val.length < 2 ? '0' + val : val
7.2 实现一个方法 queryURLParameter 获取一个URL地址问号后面传递的参数信息
实际应用:
通过列表中的信息进入同一个详情页,不同的信息在同一个详情页中同样结构不同内容
浏览器是如何区分不同信息的呢? 通过URL传递的不同参数来区分
普通情况:
let url = 'http://www.lorem.cn/index.html?lx=1&name=cola&favorite=aaa#box';
// #后面是哈希值 哈希路由通过不同的哈希值展示不同的内容渲染不同信息
/*
* 结果:{
lx:1,
name:'cola',
favorite:'aaa',
HASH:'box'
}
*/
// 第一步 获取问号和#后面的值
let askIndex = url.indexOf('?'),
wellIndex = url.indexOf('#'),
askText = url.substring(askIndex+1,wellIndex);
wellText = url.substring(wellIndex+1)
console.log(askText,wellText); // => 'lx=1&name=cola&favorite=aaa' 'box'
// 第二步 问号后面值的详细处理
// 拆
let askAry = askText.split('&');
console.log(askAry); // => ['lx=1', 'name=cola', 'favorite=aaa']
// 循环放入对象
let result ={};
askAry.forEach(item=>{
// item: 当前从数组中循环的这一项 eg: 'lx=1'
// 再拆
let key = item.split('=')[0],
value = item.split('=')[1];
// 将拆的内容依次放入对象中
result[key]=value;
});
console.log(result); // => {lx: '1', name: 'cola', favorite: 'aaa'}
// 处理哈希值
result['HASH'] = wellText;
console.log(result); // => {lx: '1', name: 'cola', favorite: 'aaa', HASH: 'box'}
图解:
封装成方法:
<script>
/*
queryURLParams: 获取URL地址中问号传参的信息和哈希值
@params
url[string] 要解析的URL字符串
@return
[object] 包含参数和哈希值信息的对象
by Ark on 2019/07/24 16:29:00
*/
// 考虑更多的细节: ? 和 # 不一定都存在
function queryURLParams(url) {
//第一步 获取 ? 和 # 后面的信息
let askIn = url.indexOf('?'),
wellIn = url.indexOf('#'),
askText = '',
wellText = '';
wellIn === -1 ? wellIn = url.length : null;
// # 如果不存在 就让url末尾新增一位,放wellIn ;否则,啥也不做 [null只是占位, 什么都不做, 也没有赋值给wellIn]
if (askIn >= 0) {
// ? 存在
askText = url.substring(askIn + 1, wellIn);
// substring参数 (n,m) 从n开始,截取到m,不包括m
// 如果 # 存在, 那就截取到 wellIn 前一位为止;
// 如果wellIn不存在,那也截取到了原索引为url.length的前一位,也就是原索引为url.length - 1 ,正好实现了截取到末尾的功能
};
wellText = url.substring(wellIn + 1);
// #存在,则截取#后面到字符串末尾 ; #不存在,wellIn = url.length ,索引在url.length + 1时是没有字符串的 所以什么都没截取到
// 第二步 截取每一部分信息
let result = {};
wellText !== '' ? result['HASH'] = wellText : null;
if (askText !== '') {
let ary = askText.split('&');
ary.forEach(item => {
let itemAry = item.split('=');
result[itemAry[0]] = itemAry[1];
})
}
return result;
};
let url = 'https://www.yuque.com/login?goto=https%3A%2F%2Fwww.yuque.com%2Fdashboard&wewrwe=232342342&sdsd=123123';
let paramsObj = queryURLParams(url);
console.log(paramsObj); // => {goto: 'https%3A%2F%2Fwww.yuque.com%2Fdashboard', wewrwe: '232342342', sdsd: '123123'}
</script>
正则:
function queryURLParams(url){
let result = {};
let reg1 = /([^?=&#]+)=([^?=&#]+)/g,
reg2 = /#(\.)+/;
// _ 表示大正则捕获的内容,此处不需要,习惯性的用_占个位
url.replace(reg1,(_,x,y)=>{
result[x] = y;
});
url.replace(reg2,(_,x)=>{
result["HASH"] = x;
});
return result;
}
let url1 = 'https://www.yuque.com/login?goto=https%3A%2F%2Fwww.yuque.com%2Fdashboard&wewrwe=232342342&sdsd=123123';
let paramsObj1 = queryURLParams(url1);
console.log(paramsObj1); // => {goto: 'https%3A%2F%2Fwww.yuque.com%2Fdashboard', wewrwe: '232342342', sdsd: '123123'}
7.3 实现四位随机验证码
此处是最简单的验证码 : 数字 + 字母
验证码目的 : 防止外挂程序恶意批量注入等
<!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>
</head>
<body>
<input type="text" id="codeInp">
<br>
<span id="codeBox"></span>
<button id="changeCode">看不清,换一张</button>
<!-- IMPORT JS -->
<script>
let codeInp = document.getElementById('codeInp'),
codeBox = document.getElementById('codeBox'),
changeCode = document.getElementById('changeCode');
/*
queryCode: 获取到四位随机的验证码, 然后放到指定的盒子中
@ params
@ return
by Ark on 2019/07/24
*/
// 多次使用,所以封装成方法
function queryCode(){
// 准备获取范围的字符串
let area = '0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM';
let result = '';
for (let i = 0; i < 4; i++) {
// 每次循环都获取一个随机的数字索引
let ran = Math.round(Math.random()*61);
// 再根据获取的索引从范围字符串中找到对应的字符, 把找到的字符拼接到最后的结果当中
result += area.charAt(ran);
}
// 把结果放到盒子里
codeBox.innerHTML = result;
}
// 第一次加载页面需要执行方法, 让其显示在页面中
queryCode();
// 点击看不清按钮,需要重新执行方法生成新的验证码
changeCode.onclick = queryCode; // 不能加小括号,加了小括号相当于把执行结果给点击事件.其实要的是点击事件调用方法.
// 文本框失去焦点的时候, 验证用户输入的内容和验证码是否相同, 并给予相关提示; 如果不一样需要重新生成验证码(防止对方一直试 试出来)
// onblur 文本框失去焦点事件
codeInp.onblur = function (){
// 获取用户和验证码内容 (表单元素用 .value ; 非标单元素用 .innerHTML)
let val = codeInp.value,
code = codeBox.innerHTML;
if(val.toLowerCase() === code.toLowerCase()){
alert('温馨提示: 输入成功!')
}else{
alert('温馨提示: 验证码输入有误,请重试!');
// 错误后 让文本框清空
codeInp.value = '';
//重新生成验证码
queryCode();
}
};
</script>
</body>
</html>