<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
html,
body {
width: 100%;
height: 100%;
}
table {
border-collapse: collapse;
width: 100%;
}
th,
td {
border: 1px solid black;
padding: 8px;
text-align: center;
}
th {
background-color: rgb(162, 162, 162);
}
.overlay {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .3);
position: fixed;
top: 0;
left: 0;
}
.add_user_box {
width: 350px;
height: 130px;
background-color: beige;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 15px;
padding: 20px;
}
.add_user_box input {
width: 300px;
}
.btn_box {
width: 100%;
position: absolute;
bottom: 30px;
display: flex;
justify-content: center;
}
.btn_box button {
width: 100px;
height: 30px;
}
.close {
display: none;
}
</style>
</head>
<body>
<button id="sort_btn">排序</button>
<button id="add_btn">新增</button>
<button id="get_age">获取平均年龄</button>
<table></table>
<!-- 遮罩层 -->
<div class="overlay close"></div>
<!-- 弹出层 -->
<div class="add_user_box close">
姓名: <input type="text" class="username">
<br>
年龄: <input type="text" class="userage">
<br>
城市: <input type="text" class="usercity">
<br>
<br>
<div class="btn_box">
<button class="close_box_btn">取消</button>
<button class="add_user_btn">新增用户</button>
</div>
</div>
<script>
var data = JSON.parse(window.localStorage.getItem('data')) || [
{
status: true,
id: 1,
name: '张三',
age: 25,
city: '北京',
},
{
status: false,
id: 2,
name: '李四',
age: 30,
city: '上海',
},
{
status: true,
id: 3,
name: '王五',
age: 22,
city: '杭州',
}
]
// 页面打开时调用渲染函数
bindHtml()
// 创建一个渲染函数
function bindHtml() {
// 在页面渲染前, 先清空之前的页面
document.querySelector('table').innerHTML = ""
// 在页面渲染前, 先计算出有多少个数据被选中, 用于决定是否选中全选
var checkedNum = 0 // 存储当前数据中 有多少个数据被选中了
for (var q = 0; q < data.length; q++) {
data[q].status && checkedNum++ // 如果当前对象的status属性为 true, 那么代表当前对象被选中了, 所以计数器 + 1
}
// ==================创建表头内容开始==================
var headerArr = ['选择', '编号', '姓名', '年龄', '城市']
var headerTr = document.createElement('tr') // 当前tr只需要创建一个, 内部放一些 th 也就是 表头
for (var j = 0; j < headerArr.length; j++) { // 根据数据批量创建表头
var headerTh = document.createElement('th') // 创建一个表头
if (j === 0) { // 如果 j === 0, 代表循环第一次执行, 那么这个单元格的内容, 应该是一个多选框
var inp = document.createElement('input') // 创建一个 input 标签, 注意: 默认为 输入框
inp.type = 'checkbox' // 如果没有这一行那么创建的默认是一个 单行文本输入框
inp.className = 'check_all' // 因为一会需要添加事件, 所以这里提前给这个选择框添加一个类名标识
inp.checked = checkedNum === data.length // 根据 现有选中的数据数量和总数据数量对比, 如果相同代表所有数据被选中, 那么选中全选按钮
headerTh.appendChild(inp) // 将 多选框 添加到 th 中
} else {
headerTh.innerHTML = headerArr[j] // 给表头单元格赋值一个文本
}
headerTr.appendChild(headerTh) // 将 th 单元格 放到 tr 单元行 内
}
document.querySelector('table').appendChild(headerTr)
// ==================创建表头内容结束==================
// ==================创建表格内容开始==================
for (var i = 0; i < data.length; i++) {
var myTr = document.createElement('tr')
var dataKeys = Object.keys(data[i])
for (var k = 0; k < dataKeys.length; k++) {
var myTd = document.createElement('td')
// 如果 展示的内容是一个 布尔值, 那么应该展示一个多选框
if (data[i][dataKeys[k]] === true || data[i][dataKeys[k]] === false) {
var inpItems = document.createElement('input') // 创建一个 input 标签, 注意: 默认为单行输入框
inpItems.type = 'checkbox' // 更改类型为 多选框
inpItems.className = 'check_item' // 给多选框添加类名, 因为一会需要添加事件
inpItems.checked = data[i][dataKeys[k]] // 给多选框 添加一个默认的选中状态, 需要根据数据提供的来展示
inpItems.dataset.id = i + 1 // 用于给 标签 添加一个 标识, 能够知道将来点的是那个
myTd.appendChild(inpItems)
// 将 多选框 添加到 td 单元格中
} else {
myTd.innerText = data[i][dataKeys[k]] // 如果 展示的内容不是 布尔值, 那么正常展示文本
}
myTr.appendChild(myTd)
}
document.querySelector('table').appendChild(myTr)
}
// ==================创建表格内容结束==================
// ==================持久化数据==================
window.localStorage.setItem('data', JSON.stringify(data))
}
// ==================全选功能 (事件委托) 开始==================
var myTable = document.querySelector('table')
myTable.onclick = function (e) {
if (e.target.className === 'check_all') {
// 1. 修改数据
for (var i = 0; i < data.length; i++) {
data[i].status = e.target.checked
}
// 2. 重新渲染页面
bindHtml()
}
if (e.target.className === 'check_item') {
// 1. 修改数据
for (var k = 0; k < data.length; k++) {
if (e.target.dataset.id - 0 === data[k].id) {
data[k].status = e.target.checked
}
}
// 2. 重新渲染页面
bindHtml()
}
}
// ==================全选功能 (事件委托) 结束==================
// ==================排序功能开始==================
var sortBtn = document.querySelector('#sort_btn')
var num = 0
sortBtn.onclick = function () {
num++ // 每次点击的时候 修改计数器的数字
if (num === 1) { // 1. 第一次点击 按照 年龄的从小到大
data.sort(function (a, b) { return a.age - b.age })
} else if (num === 2) { // 2. 第二次点击 按照 年龄的从大到小
data.sort(function (a, b) { return b.age - a.age })
} else { // 3. 第三次点击 恢复默认排序(按照ID从小到大)
data.sort(function (a, b) { return a.id - b.id })
num = 0 // 清零计数器, 下次可以重新执行逻辑
}
// 上述的 if 语句内 处理完数据后, 重新渲染页面
bindHtml()
}
// ==================排序功能结束==================
// ==================新增功能开始==================
// 1. 点击 "新增按钮" 打开 遮罩层 和 信息框
var addBtn = document.querySelector('#add_btn')
var overlay = document.querySelector('.overlay')
var addUserBox = document.querySelector('.add_user_box')
addBtn.onclick = function () {
overlay.classList.remove('close')
addUserBox.classList.remove('close')
}
// 2. 点击 "新增用户按钮" 收集用户输入的信息, 然后创建一个对象, 追加到原数组的末尾, 最后重新渲染页面
var addUserBtn = document.querySelector('.add_user_btn')
addUserBtn.onclick = function () {
// 2.1 获取到用户输入的信息
var nameEl = document.querySelector('.username')
var ageEl = document.querySelector('.userage')
var cityEl = document.querySelector('.usercity')
var nameValue = nameEl.value
var ageValue = ageEl.value
var cityValue = cityEl.value
// 2.2 安全校验 (非空校验, 规则校验/正则校验)
if (nameValue === '' || ageValue === '' || cityValue === '') return alert('您的输入框有一个为空, 请补全输入框')
// 2.3 如果代码能够正常执行到这里, 说明输入框的的内容不是空的, 所以可以组装一个对象, 然后追加到原数组的末尾
var obj = {
status: false,
id: data.length + 1,
name: nameValue,
age: ageValue - 0,
city: cityValue,
}
data.push(obj)
// 2.4 调用渲染函数
bindHtml()
// 2.5 清空弹框数据
nameEl.value = ''
ageEl.value = ''
cityEl.value = ''
// 2.6 关闭弹框
closeBoxFn()
}
// 3. 点击 "取消按钮" 关闭 遮罩层和信息框
var closeBoxBtn = document.querySelector('.close_box_btn')
closeBoxBtn.onclick = closeBoxFn
function closeBoxFn() {
overlay.classList.add('close')
addUserBox.classList.add('close')
}
// ==================新增功能结束==================
// ==================获取平均年龄开始==================
var getAge = document.querySelector('#get_age')
getAge.onclick = function () {
// 1. 获取到年龄的总和
var sum = 0
for (var i = 0; i < data.length; i++) {
sum += data[i].age
}
// 2. 总和 / 总数量 === 年龄的平均值
sum = sum / data.length
// 3. 提示给用户年龄的平均值
alert(sum.toFixed(1))
}
// ==================获取平均年龄结束==================
</script>
</body>
</html>
```