第三章 浏览器 【5. 事件】
5. 事件
5.3 事件对象
1. 坐标属性
// 1. 相对于浏览器窗口的坐标
event.clientX
event.clientY
// 2. 相对于元素边界的坐标
event.offsetX
event.offsetY
// 3. 相对于页面边界的坐标
event.pageX
event.pageY
<div style="width: 500px;height: 1000px;background-color:darkcyan;"></div><button id="btn1">按钮</button><script>document.getElementById('btn1').onclick = function (event) {// alert('程序流程')console.log(event);//事件对象,描述当前对象发生的所有信息数据的集合// 相对窗口坐标console.log(event.clientX);console.log(event.clientY);// 相对于元素边界的坐标位置!console.log(event.offsetX);console.log(event.offsetY);// 相对于页面的坐标位置console.log(event.pageX);console.log(event.pageY);//事件目标console.log(event.target);//buttonconsole.log(event.type);}</script>2. 常用属性
- type - 事件类型
- target - 事件目标元素
- currentTarget - 当前处理事件的元素
3. 键盘事件特殊属性
- key - 按键名称
- keyCode - 按键码值(已废弃,建议使用key)
案例:跟随鼠标移动
<style>img {position: absolute;margin: 0;padding: 0;}</style><img src="./F80C289E297159FCAF84E44766651E04.png" alt="" srcset=""><script>//当鼠标开始移动document.onmousemove = function (event) {let x = event.pageXlet y = event.pageY//修改top,leftdocument.querySelector('img').style.left = x + 'px'document.querySelector('img').style.top = y + "px"}</script>
4. 事件目标、事件源
<div class="box"><span>盒子</span></div><a href="./01-关于事件.html">跳转</a><script>//事件源document(挂载类型的目标对象)document.onclick = function (event) {// console.log(event);//事件对象console.dir(event.target);//事件目标(事件触发的元素)}//阻止默认行为document.querySelector("a").onclick = function (e) {e.preventDefault()}</script>5. 事件控制方法
// 阻止默认行为
event.preventDefault()
// 阻止事件冒泡
event.stopPropagation()
// 阻止默认行为和冒泡(jQuery中常用)
return false6. 事件流程
<!--事件流:捕获阶段、目标阶段、冒泡阶段 --><div class="box"><span style="background:darkgreen;">盒子</span></div><script>documentlet $html = document.documentElementlet $body = document.bodylet $div = document.querySelector('.box')let $span = document.querySelector('span')/*事件默认冒泡的过程*/document.onclick = function () {console.log('document被点了')}$html.onclick = function () {console.log('html被点了');}$body.onclick = function () {console.log('body被点了')}$div.onclick = function () {console.log('div被点了');}$span.onclick = function (event) {console.log('span被点了');// 阻止冒泡event.stopPropagation();}// 捕获流程$span.addEventListener('click', function () {console.log('span捕获');}, true)//是否是捕获过程true$div.addEventListener('click', function () {console.log('div捕获');}, true)$body.addEventListener('click', function () {console.log('body捕获');}, true)$html.addEventListener('click', function () {console.log('html捕获');}, true)document.addEventListener('click', function () {console.log('document捕获');}, true)</script>5.4 高级事件处理
1. 事件委托
<!-- 事件委托/事件代理【B必须是A的祖先元素】 --><!-- 事件委托:把本应该挂载在A元素上的事件监听,挂到B上事件代理:使用挂载在B上的事件程序代理A完成监听 --><ul><li>1</li><li>2</li><li>3</li></ul><button id="btn">添加</button><script>let $ul = document.querySelector('ul')let $lis = $ul.querySelectorAll('li')//普通事件监听// $lis.forEach(li => {// li.onclick = function () {// console.log(this);//事件源// alert(this.innerHTML)// }// })//事件委托 解决新增元素程序正常运行最好用的技术$ul.onclick = function (e) {// alert('点了')//事件目标console.dir(e.target);if (e.target.tagName == "LI") {alert(e.target.innerHTML);}}//添加功能btn.onclick = function () {let liNew = document.createElement('li')liNew.innerHTML = '新内容'$ul.append(liNew)}</script>5.5 员工信息表案例
1. 案例概述
基于HTML、CSS、JavaScript实现的员工信息管理系统,具备完整的CRUD(增删改查)功能。
2. 核心功能
2.1 数据展示
表格形式展示员工信息(工号、姓名、薪资、操作)
动态渲染数据到HTML表格
2.2 新增员工
弹窗输入新员工信息
自动生成递增工号
数据验证和保存
2.3 编辑员工
点击编辑按钮显示当前数据
修改后更新数据并重新渲染
2.4 删除员工
确认对话框防止误删
从DOM和数据中移除记录
3. 关键技术实现
3.1 数据结构
// 员工数据对象
{employeeId: 'EMP001', // 工号name: '张三', // 姓名department: '技术部', // 部门position: '工程师', // 职位age: 28, // 年龄salary: 8000 // 薪资
}
// 核心变量
let employees = [/* 员工数据数组 */]
let editIndex = -1 // 编辑索引(-1表示新增模式)
let num = 3 // 工号计数器3.2 渲染函数
function renderTable(arr) {let htmlStr = ''arr.forEach(function (item) {htmlStr += `<tr><td>${item.employeeId}</td><td>${item.name}</td><td>${item.salary}</td><td><button class="edit">编辑</button><button class="del">删除</button></td></tr>`})document.querySelector('table tbody').innerHTML = htmlStr
}3.3 事件委托处理
// 统一处理编辑和删除操作
document.querySelector('table tbody').onclick = function (e) {if (e.target.className == "edit") {// 编辑逻辑let tr = e.target.closest('tr')let td1 = tr.querySelectorAll('td')[0].innerTextlet td2 = tr.querySelectorAll('td')[1].innerTextlet td3 = tr.querySelectorAll('td')[2].innerTexteditIndex = employees.findIndex(item => item.employeeId == td1)uname.value = td2usalary.value = td3mask.hidden = falseiptBox.hidden = false}if (e.target.className == "del") {let ok = confirm('你确定删除吗')if (ok) {e.target.closest('tr').remove()}}
}3.4 提交处理
subBtn.onclick = function () {if (editIndex < 0) {// 新增模式let userObj = {employeeId: 'EMP' + ++num,name: uname.value,salary: usalary.value}employees.push(userObj)alert('新增成功')} else {// 编辑模式employees[editIndex].name = uname.valueemployees[editIndex].salary = usalary.valuealert('修改成功')editIndex = -1}renderTable(employees)uname.value = ''usalary.value = ''mask.hidden = trueiptBox.hidden = true
}4. 技术亮点
4.1 事件委托
统一处理动态生成的按钮事件
减少事件监听器数量,提升性能
4.2 数据驱动视图
数据变化后自动重新渲染表格
保持数据和视图同步
4.3 模态弹窗
遮罩层防止误操作
居中显示提供良好体验
5. 实现流程
5.1 新增流程
点击新增 → 显示弹窗 → 填写信息 → 提交保存 → 重新渲染 → 隐藏弹窗
5.2 编辑流程
点击编辑 → 获取数据 → 填充表单 → 修改信息 → 更新数据 → 重新渲染
5.3 删除流程
点击删除 → 确认对话框 → 移除DOM元素
6. 优化建议
删除功能再完善
// 同步更新数据数组
if (ok) {let tr = e.target.closest('tr')let employeeId = tr.querySelectorAll('td')[0].innerTextemployees = employees.filter(item => item.employeeId !== employeeId)tr.remove()
}这个案例展示了:
- 前端CRUD操作的完整实现
- 事件委托的实际应用
- 数据驱动视图的编程思想
- 模态弹窗的交互设计
- JavaScript DOM操作技巧
