一、Window对象
01- BOM
BOM(Browser Object Model ) 是浏览器对象模型
window 是浏览器内置中的全局对象,我们所学习的所有 Web APIs 的知识内容都是基于 window 对象实现的
- window 对象下包含了 navigator、location、document、history、screen 5个属性,即所谓的 BOM (浏览器对象模型)
- document 是实现 DOM 的基础,它其实是依附于 window 的属性。
注:依附于 window 对象的所有属性和方法,使用时可以省略 window
02- 定时器-延时函数
JavaScript 内置的一个用来让代码延迟执行的函数,叫 setTimeout
- 语法:
setTimeout('回调函数',等待的毫秒数);
// setTimeout(function(){console.log('回调函数');},1000);
function fn(){
console.log('回调函数');
}
setTimeout(fn,1000);
setTimeout 仅仅只执行一次,所以可以理解为就是把一段代码延迟执行, 平时省略window
- 清除延时函数
let timer = setTimeout('回调函数',等待的毫秒数);
//清除延时函数:
clearTimeout(timer)
<body>
<button>延迟执行某个操作</button>
<button>解除延迟器</button>
<script>
let btn1 = document.querySelector('button:nth-of-type(1)')
let btn2 = document.querySelector('button:nth-of-type(2)')
// 添加延迟器
// let 标识 = setTimeout(function() {
// // 延迟执行的操作
// }, 延迟时间)
let tid
btn1.addEventListener('click', function() {
tid = setTimeout(function() {
console.log(123)
}, 2000)
})
btn2.addEventListener('click', function() {
// clearTimeout(tid)
// 通过setTimeout开启的延迟器,通过clearInterval也能清除,反之亦然
clearInterval(tid)
})
</script>
</body>
03- 5s消失的小广告
<!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>
img {
position: absolute;
left: 0;
bottom: 0;
}
</style>
</head>
<body>
<button>返回</button>
<img src="./images/ad.png" alt="" />
<script>
let btn = document.querySelector('button')
let img = document.querySelector('img')
setTimeout(() => {
img.style.display = 'none'
}, 5000)
btn.addEventListener('click', function() {
// history.back()
history.go(-10)
})
</script>
</body>
</html>
04-自定义消息提示
<!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>Document</title>
<style>
.tip {
max-width: 200px;
padding: 10px 20px;
background-color: rgba(0, 0, 255, 0.2);
margin: 200px auto;
border-radius: 5px;
text-align: center;
opacity: 0;
transition: all 1s;
}
</style>
</head>
<body>
<button>登陆</button>
<div class="tip"></div>
<script>
let btn = document.querySelector('button')
let tip = document.querySelector('.tip')
// 模拟 框架中的 消息提示:
// 1.弹出,3秒自动消失 -- 添加延迟器
// 2.如果鼠标进入,不消失 -- 清除延迟器
// 3.如果鼠标移开,3秒之后消失 -- 再次添加延迟器
btn.addEventListener('click',
function() {
tip.innerHTML = '登陆成功'
tip.style.opacity = 1
// 显示3s再消失
let tid = setTimeout(() => {
tip.style.opacity = 0
}, 3000)
// 鼠标进入,清除延迟器
tip.addEventListener('mouseenter', function() {
clearTimeout(tid)
})
// 鼠标离开,重启延迟器
tip.addEventListener('mouseleave', function() {
tid = setTimeout(() => {
tip.style.opacity = 0
}, 3000)
})
}
)
</script>
</body>
</html>
05-利用递归实现setInterval
<body>
<div></div>
<script>
let div = document.querySelector('div')
// 递归 是指 函数直接或间接调用自身
function showTime() {
let time = new Date().toLocaleTimeString()
div.innerHTML = time
setTimeout(showTime, 1000)
}
showTime()
</script>
</body>
05-递归函数:函数内部调用其自身
function fn(n){
if(n ===0){
return;
}
fn(n-1)
console.log(n);
}
fn(5)
结合递归函数可以使用 setTimeout 实现 setInterval 一样的功能
<body>
<div class="clock"></div>
<script>
let clock = document.querySelector('.clock');
function timer() {
let date = new Date();
clock.innerHTML = date.toLocaleString();
setTimeout(timer,1000)
}
timer();
</script>
两种定时器对比:
- setInterval 的特征是重复执行,首次执行会延时
- setTimeout 的特征是延时执行,只执行 1 次
- setTimeout 结合递归函数,能模拟 setInterval 重复执行
- clearTimeout 清除由 setTimeout 创建的定时任务
经典面试题
<script>
console.log(111);
setTimeout(function(){
console.log(222);
},1000)
console.log(333);
//111
//333
//222
console.log(111);
setTimeout(function(){
console.log(222);
},1000)
console.log(333);
//111
//333
//222
</script>
06- JS 执行机制
以下代码执行的结果是什么?
console.log(1);
setTimeout(function () {
console.log(3);
}, 1000);
console.log(2);//1,3,2
console.log(1);
setTimeout(function () {
console.log(3);
}, 0);
console.log(2);//1,3,2
JS 是单线程
JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。 这是因为 Javascript 这门脚本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
同步任务和异步任务
单线程导致的问题就是后面的任务等待前面任务完成,如果前面任务很耗时(比如读取网络数据),后面任务不得不一直等待!!
为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制。于是,JS 中出现了同步任务和异步任务。
同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。
异步
你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。
他们的本质区别: 这条流水线上各个流程的执行顺序不同。
JS中所有任务可以分成两种
- 同步任务(synchronous)
在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务; 2. 异步任务(asynchronous) 不进入主线程、而进入”任务队列”的任务,当主线程中的任务运行完了,才会从”任务队列”取出异步任务放入主线程执行。
JS执行机制(事件循环)
- 先执行执行栈中的同步任务。
- 异步任务放入任务队列中。
- 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
思考:
console.log(1)
document.addEventListener('click', function () {
console.log(4)
})
console.log(2)
setTimeout(function () {
console.log(3)
}, 3000)
图例小结
07- location对象
-
location 的数据类型是对象,它拆分并保存了 URL 地址的各个组成部分
-
常用属性和方法:
- href 属性获取完整的 URL 地址,对其赋值时用于地址的跳转
- search 属性获取地址中携带的参数,符号 ?后面部分
- hash 属性获取地址中的啥希值,符号 # 后面部分 VUE中使用
- reload 方法用来刷新当前页面,传入参数 true 时表示强制刷新
- reload 方法用来刷新当前页面,传入参数 true 时表示强制刷新
<body>
<button>帮我跳转到某个页面</button>
<script>
let btn = document.querySelector('button')
btn.addEventListener('click', function() {
// location.href
// 1.没有赋值就是取值
// 2.赋值正确的地址就可以实现跳转
// 跳转的路径可以是 绝对路径也可以是相对路径
// location.href = "https://www.baidu.com/s?wd=%E8%91%B1%E7%88%86%E8%82%89&rsv_spt=1&rsv_iqid=0xcdf6be0000002179&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=02003390_19_hao_pg&rsv_dl=ib&rsv_enter=1&rsv_sug3=4&rsv_sug1=2&rsv_sug7=100"
// location.href = './03-5秒消失的广告.html'
location.reload()
})
</script>
</body>
08-5秒钟之后跳转页面
<!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>
span {
color: red;
}
</style>
</head>
<body>
<button>forward</button>
<a href="./13-history对象.html">支付成功,<span>5</span> 秒之后跳转首页</a>
<script>
// 如果单击,则自动的跳转,如果不单击则5秒之后自动跳转
let span = document.querySelector('span')
let button = document.querySelector('button')
button.addEventListener('click', function() {
location.href = './03-5秒消失的广告.html'
})
let time = 5
// setTimeout(() => {}, 5000)
setInterval(function() {
time--
span.innerText = time
if (time == 0) {
location.href = './03-5秒消失的广告.html'
}
}, 1000)
</script>
</body>
</html>
09- navigator对象
- navigator的数据类型是对象,该对象下记录了浏览器自身的相关信息
- 常用属性和方法:
- 通过 userAgent 检测浏览器的版本及平台 自动检测移动端并跳转 navigator 对象包含有关浏览器的信息,它有很多属性,我们最常用的是 userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值。 下面前端代码可以判断用户那个终端打开页面,实现跳转
<script>
// 检测 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'
} else {
location.href = 'http://itcast.cn'
}
})()
</script>
1.6 histroy对象
history 的数据类型是对象,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
常用属性和方法:
history 对象一般在实际开发中比较少用,但是会在一些 OA 办公系统中见到。
2. swiper插件
01- 插件
插件: 就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果
学习插件的基本过程
- 熟悉官网,了解这个插件可以完成什么需求 [www.swiper.com.cn/]
- 看在线演示,找到符合自己需求的demo [www.swiper.com.cn/demo/index.…]
- 查看基本使用流程 [www.swiper.com.cn/usage/index…]
- 查看APi文档,去配置自己的插件 [www.swiper.com.cn/api/index.h…] 注意: 多个swiper同时使用的时候, 类名需要注意区分
3. 本地存储
01- 本地存储特性
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。
- 数据存储在用户浏览器中
- 设置、读取方便、甚至页面刷新不丢失数据
- 容量较大,sessionStorage和localStorage约 5M 左右
02- localStorage
- 生命周期永久生效,除非手动删除 否则关闭页面也会存在
- 可以多窗口(页面)共享(同一浏览器可以共享)
- 以键值对的形式存储使用
03- 本地存储使用
<body>
<button>设置本地存储</button>
<button>获取本地存储</button>
<button>删除本地存储</button>
<button>干掉所有本地存储</button>
<script>
let set = document.querySelector('button:nth-of-type(1)')
let get = document.querySelector('button:nth-of-type(2)')
let remove = document.querySelector('button:nth-of-type(3)')
let clear = document.querySelector('button:nth-of-type(4)')
// 存储数据到本地存储
set.addEventListener('click', function() {
// 语法:localStorage.setItem('自定义键','字符串值')
localStorage.setItem('key79', '随便写一个字符串就可以了')
})
get.addEventListener('click', function() {
// 语法:localStorage.getItem('键'):获取当前键所对应的值,如果没有这个键,则返回null
let v = localStorage.getItem('key79')
console.log(v)
})
remove.addEventListener('click', function() {
// 语法:localStorage.removeItem('键'):删除指定名称的本地存储:整个键值对都删除
// 键如果不存在,没事。。
localStorage.removeItem('key79')
})
clear.addEventListener('click', function() {
// localStorage.clear():删除浏览器的所有本地存储--慎用
localStorage.clear()
})
</script>
</body>
04-本地存储存储的和获取的都是字符串
<body>
<button>设置本地存储</button>
<button>获取本地存储</button>
<button>删除本地存储</button>
<script>
let set = document.querySelector('button:nth-of-type(1)')
let get = document.querySelector('button:nth-of-type(2)')
let remove = document.querySelector('button:nth-of-type(3)')
set.addEventListener('click', function() {
// let obj = { username: '黄鑫', age: 20 }
let arr = [1, 3, 5, 7, 9]
// 1.本地存储只能存储字符串格式,如果你传递的数据不是字符串,那么它会自动将数据转换为字符串
localStorage.setItem('key-79-info', arr)
})
</script>
</body>
存储复杂数据类型存储
本地只能存储字符串,无法存储复杂数据类型.需要将复杂数据类型转换成JSON字符串,在存储到本地
JSON.stringify(复杂数据类型)
将复杂数据转换成JSON字符串 存储 本地存储中
let a = JSON.stringify(obj);
console.log(a);
localStorage.setItem('student', a);
let b = localStorage.getItem('student');
console.log(b);
JSON.parse(JSON字符串)
将JSON字符串转换成对象 取出 时候使用
let c = JSON.parse(b);
console.log(c);
05- 本地存储存储数组
<body>
<button>设置本地存储</button>
<button>获取本地存储</button>
<button>删除本地存储</button>
<button>干掉所有本地存储</button>
<script>
let arr = [
{
stuId: 1001,
uname: '欧阳霸天',
age: 19,
gender: '男',
salary: '20000',
city: '上海'
},
{
stuId: 1002,
uname: '令狐霸天',
age: 29,
gender: '男',
salary: '30000',
city: '北京'
},
{
stuId: 1003,
uname: '诸葛霸天',
age: 39,
gender: '男',
salary: '2000',
city: '北京'
}
]
let set = document.querySelector('button:nth-of-type(1)')
let get = document.querySelector('button:nth-of-type(2)')
set.addEventListener('click', function() {
// localStorage.setItem('key79', arr)
// let obj = {
// stuId: 1001,
// uname: '欧阳霸天',
// age: 19,
// gender: '男',
// salary: '20000',
// city: '上海'
// }
// // 将obj转换为对象的字符串格式 -- json格式
// // JSON.stringify(对象) 》》json字符串
// localStorage.setItem('key79', JSON.stringify(obj))
// let arr = [1, 3, 5, 7, 9]
// localStorage.setItem('key79', JSON.stringify(arr))
localStorage.setItem('key79', JSON.stringify(arr))
})
get.addEventListener('click', function() {
// 获取到的本地存储数据默认是字符串
// JSON.parse(json字符串):将json字符串转换为js对象(数组)
let v = localStorage.getItem('key79')
console.log(v, typeof v)
console.log(JSON.parse(v), typeof JSON.parse(v))
// 面向对象编程
})
</script>
</body>
06- sessionStorage(了解)
- 生命周期为关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享
- 以键值对的形式存储使用
- 用法跟localStorage 基本相同
<body>
<button>设置本地存储</button>
<button>获取本地存储</button>
<button>删除本地存储</button>
<script>
let set = document.querySelector('button:nth-of-type(1)')
let get = document.querySelector('button:nth-of-type(2)')
let remove = document.querySelector('button:nth-of-type(3)')
set.addEventListener('click', function() {
sessionStorage.setItem('aa', 'aaaaa')
})
</script>
</body>
07- 综合案例 本地存储学习信息案例
需求:改为本次存储版本的学习信息表
分析:
需求①:读取本地存储数据(封装函数)
如果本地存储有数据,则返回 JSON.parse() 之后的对象
如果本地存储没有数据,则默认写入三条数据,注意存储的利用JSON.stringify() 存 储JSON 格式的数据
需求②:渲染模块
先读取本地存储数据,然后渲染
需求③:添加模块
注意,先取的最新的本地存储数据,然后追加
新增了数据,要把新数据存储到本地存储别,忘记转换
<!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>Document</title>
<link rel="stylesheet" href="css/user.css" />
</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>
// 模拟数据:数据一定要有id作为数据的唯一标识,这个标识是以后数据 修改和删除的凭证
let students = JSON.parse(localStorage.getItem('userinfo-79')) || [
{
id: 1,
name: '张三',
age: 18,
gender: '男',
salary: 18000,
city: '广州'
},
{
id: 2,
name: '李四',
age: 19,
gender: '男',
salary: 20000,
city: '深圳'
},
{
id: 3,
name: '王五',
age: 18,
gender: '男',
salary: 18000,
city: '广州'
},
{
id: 4,
name: '赵六',
age: 19,
gender: '男',
salary: 20000,
city: '深圳'
}
]
// 获取元素
let tbody = document.querySelector('tbody')
let add = document.querySelector('.add')
let uname = document.querySelector('.uname')
let age = document.querySelector('.age')
let gender = document.querySelector('.gender')
let salary = document.querySelector('.salary')
let city = document.querySelector('.city')
let id = 5
// 1.数据渲染
function init(){
// 遍历拼接
let htmlStr = '';
students.forEach(function(value,index){
htmlStr += `<tr>
<td>${index + 1}</td>
<td>${value.name}</td>
<td>${value.age}</td>
<td>${value.gender}</td>
<td>${value.salary}</td>
<td>${value.city}</td>
<td>
<a href="javascript:" class="del" id="${value.id}">删除</a>
</td>
</tr>`
})
tbody.innerHTML = htmlStr;
}
// 一开始需要调用函数,否则函数不会自动的执行
init()
// 2.使用事件委托绑定事件,一般情况下是绑定给最近的一级父容器
tbody.addEventListener('click',function(e){
// 判断是否是单击了删除按钮
if(e.target.className == 'del'){
// console.log(e.target);
// 实现删除:filter方法的使用
// filter是数组非变更方法,所以要将filter的结果覆盖原数组
students = students.filter(function(value){
// 假如删除id为1的值
return value.id != e.target.id
})
// 重新渲染
init()
localStorage.setItem('userinfo-79', JSON.stringify(students))
}
})
// 3.添加数据
add.addEventListener('click', function(){
// 创建新的数组对象
let newObj = {
id: id,
name: uname.value,
age: age.value,
gender: gender.value,
salary: salary.value,
city: city.value
}
id++
// 将新创建的对象添加到数组中
students.push(newObj);
// 重新渲染数据
init()
// 存储本地数据
localStorage.setItem('userinfo-79', JSON.stringify(students))
})
</script>
</body>
</html>
拓展: 自定义属性
-
固有属性:
- 标签天生自带的属性 比如class id title等, 可以直接使用点语法操作
-
自定义属性:
由程序员自己添加的属性,在DOM对象中找不到, 无法使用点语法操作,必须使用专门的API
- getAttribute('属性名') // 获取自定义属性
- setAttribute('属性名', '属性值') // 设置自定义属性
- removeAttribute('属性名') // 删除自定义属性
自定义属性操作api
<body>
<p index="1" class="abc">我是p元素</p>
<input type="checkbox" checked />
<button>添加一个自定义属性</button>
<button>获取一个自定义属性</button>
<button>移除一个自定义属性</button>
<script>
let p = document.querySelector('p')
let input = document.querySelector('input')
let btn1 = document.querySelector('button:nth-of-type(1)')
let btn2 = document.querySelector('button:nth-of-type(2)')
let btn3 = document.querySelector('button:nth-of-type(3)')
btn1.addEventListener('click', function() {
p.setAttribute('myname', 'jack')
p.setAttribute('id', 'jack')
})
btn2.addEventListener('click', function() {
// 结论:通过 元素.属性只能获取内置属性的值,不能获取非内置属性的值
// console.log(p.index)
// getAttribute('自定义属性名称'):可以获取内置和非内置属性的值,但是它不能获取状态值(checked...)
// 最大缺点:获取值的时候一次只能获取一个自定义属性值,并且调用api赋值完全不适合遍历拼接(动态渲染)
console.log(p.getAttribute('class'))
console.log(input.getAttribute('checked'))
})
btn3.addEventListener('click', function() {
p.removeAttribute('myname')
})
</script>
</body>
data-自定义属性:
- 传统的自定义属性没有专门的定义规则,开发者随意定值,不够规范,所以在html5中推出来了专门的data-自定义属性 在
- 标签上一律以data-开头
- 在DOM对象上一律以dataset对象方式获取
<body>
<!-- 自定义属性的规范,以data-开头 如 data-myname='jack' -->
<p class="red" data-name="jack" data-age="20" data-gender="男">
我是p元素
</p>
<button>获取自定义属性的值</button>
<script>
let btn = document.querySelector('button')
let p = document.querySelector('p')
btn.addEventListener('click', function() {
// 获取p元素的自定义属性值
// 通过元素的dataset属性获取所有data-开头的自定义属性值,返回一个对象
console.log(p.dataset)
console.log(p.dataset.name)
})
</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>Document</title>
<style>
div {
width: 400px;
height: 400px;
border: solid;
}
</style>
</head>
<body>
<!-- 自定义属性:非内置属性
img.src p.id input.value -->
<table border="1" width="400">
<thead>
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- <tr>
<td>学号</td>
<td>姓名</td>
<td>年龄</td>
<td>性别</td>
<td><a href="#">编辑</a></td>
</tr> -->
</tbody>
</table>
<div>
姓名: <input type="text" class="username" /> <br />
年龄 <input type="text" class="userage" /> <br />
性别 <input type="text" class="usergender" /> <br />
<button class="userEdit">编辑</button>
</div>
<script>
let username = document.querySelector('.username')
let userage = document.querySelector('.userage')
let usergender = document.querySelector('.usergender')
let tbody = document.querySelector('tbody')
let userEdit = document.querySelector('.userEdit')
let datas = [
{ id: 1, name: 'jack', age: 20, gender: '男' },
{ id: 2, name: 'rose', age: 19, gender: '女' },
{ id: 3, name: 'tom', age: 18, gender: '男' }
]
// 渲染学员列表 -- 封装为函数,方便后期数据操作之后的重新渲染
function init(){
let htmlStr = ''
datas.forEach(function(v, i){
htmlStr += `<tr>
<td>${i + 1}</td>
<td>${v.name}</td>
<td>${v.age}</td>
<td>${v.gender}</td>
<td>
<a href="javascript:;" class="edit" data-username="${v.name}" data-userage="${v.age}" data-usergender="${v.gender}" data-id="${v.id}">编辑</a>
</td>
</tr>`
})
tbody.innerHTML = htmlStr
}
init()
let editId;
// 动态元素的事件绑定需要使用事件委托
// 单机列表中的 编辑 仅仅是进行数据回填 -- 没有做编辑操作
tbody.addEventListener('click', function(e){
// 判断
if(e.target.className == 'edit'){
// 获取当前所编辑的数据进行回填
// dataset:可以获取当前元素所有data-开头的自定义属性值,返回一个对象
let data = e.target.dataset
console.log(data); // DOMStringMap {username: 'jack', userage: '20', usergender: '男'}
editId = data.id
console.log(editId);
username.value = data.username
userage.value = data.userage
usergender.value = data.usergender
}
})
// 实现真正的编辑
userEdit.addEventListener('click', function(){
// 基于数据id进行编辑
// 我要id --- editId
// 1.根据id找到索引
for(let i = 0; i < datas.length; i++){
if(datas[i].id == editId){
// 2.根据索引进行数据编辑
datas[i].name = username.value
datas[i].age = userage.value
datas[i].gender = usergender.value
break;
}
}
init()
})
</script>
</body>
</html>