动态删除
<table>
<thead>
<tr>
<td>序号</td>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>城市</td>
<td>删除</td>
</tr>
</thead>
<tbody></tbody>
</table>
table{
border-collapse: collapse;
}
td{
width: 100px;
height: 50px;
text-align: center;
border:2px solid #000;
}
方法一:
事件委托:
给 button标签的 父级标签tbody / table 添加事件
- 1, 给 一直存在的父级标签 添加事件 执行事件委托效果
- 2, 通过 if判断 判断 e.target 是 那个标签对象
- 3, 获取 事件对象 e.target 中 index属性的属性值
- 也就是 生成 这一行标签对象 对应的数组中 对象单元的 索引下标
- 4, 根据 index属性值 作为索引下标 从 数值中删除对应的 一个单元
- 5, 再次调用函数 根据新的数组 动态渲染生成新页面
- 再次生成的页面 有些内容看似没有改变 本质上 是 新的标签
var arr = [
{id:1,name:'张三',age:18,sex:'男',addr:'北京'},
{id:2,name:'李四',age:19,sex:'女',addr:'上海'},
{id:3,name:'王五',age:20,sex:'男',addr:'广州'},
{id:4,name:'赵六',age:21,sex:'女',addr:'重庆'},
{id:5,name:'刘七',age:22,sex:'男',addr:'天津'},
];
// 调用函数 生成 动态渲染 生成标签对象
setPage();
// 事件委托
var oTbody = document.querySelector('tbody');
oTbody.addEventListener('click' , function(e){
// 通过 e.target 的 name属性 判断
if( e.target.getAttribute('name') === 'del' ){
// 执行删除程序
// 删除数组中 和 对应的删除按钮 匹配的数组中的数据
// 获取 删除对象单元的索引下标 也就是 标签中 index属性的属性值
// 获取的属性值 都是字符串类型 需要转化为数值类型
var num = e.target.getAttribute('index') - 0;
console.log( num );
// 用 index的属性值 作为 索引下标 从数组中删除一个对象
arr.splice( num , 1 );
console.log( arr );
// 再次调用函数 动态渲染生成页面
// 再次动态渲染生成的页面 内容是全新的页面内容
setPage();
}
})
function setPage(){
// 定义字符串 存储 生成的标签内容
var str = '';
// 循环遍历 数组 每一个数组单元存储数据 生成一个对应的 tr>td
// item 就是 存储数据的对象
// key 存储 对象的索引下标
arr.forEach(function(item , key){
str += `
<tr>
<td>${item.id}</td>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.sex}</td>
<td>${item.addr}</td>
<td><button name="del" index="${key}">删除</button></td>
</tr>
`;
})
// 将字符串写入到标签对象中
var oTbody = document.querySelector('tbody');
oTbody.innerHTML = str;
}
方法二:
动态生成标签的最大文件
如果直接给动态生成的标签 绑定事件
如果 重新动态生成新的标签 , 即使标签内容等完全一致,也是 覆盖的新的标签,新的标签没有绑定事件 必须要重新绑定事件
var arr = [
{id:1,name:'张三',age:18,sex:'男',addr:'北京'},
{id:2,name:'李四',age:19,sex:'女',addr:'上海'},
{id:3,name:'王五',age:20,sex:'男',addr:'广州'},
{id:4,name:'赵六',age:21,sex:'女',addr:'重庆'},
{id:5,name:'刘七',age:22,sex:'男',addr:'天津'},
];
// 调用函数 生成 动态渲染 生成标签对象
setPage();
function setPage(){
// 定义字符串 存储 生成的标签内容
var str = '';
// 循环遍历 数组 每一个数组单元存储数据 生成一个对应的 tr>td
// item 就是 存储数据的对象
arr.forEach(function(item){
str += `
<tr>
<td>${item.id}</td>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.sex}</td>
<td>${item.addr}</td>
<td><button name="del">删除</button></td>
</tr>
`;
})
// 将字符串写入到标签对象中
var oTbody = document.querySelector('tbody');
oTbody.innerHTML = str;
// 动态生成的标签 将 直接绑定事件的语法 定义在 生成页面的函数中
// 也就是 生成标签的同时 就 执行绑定事件
// 动态渲染生成标签 和 给标签绑定事件 是 同步执行的
// 获取所有的button删除标签,循环遍历绑定点击事件
var oBtns = document.querySelectorAll('[name="del"]');
oBtns.forEach(function (item, key) {
// item 是 button按钮
// key 是 button按钮的索引下标 也就是 数组中对应对象的索引下标
item.addEventListener('click', function () {
// 根据 button的索引下标 删除 数组的对象
arr.splice(key, 1);
console.log(arr);
// 调用函数 再次动态渲染生成页面
// 重新动态渲染生成页面 会重新生成标签 会覆盖之前的标签
// 新的标签覆盖之前的标签,绑定的事件就没有了
setPage();
})
})
}
总结 动态渲染 事件绑定语法的区别
-
直接绑定:
可以获取索引下标等 不用单独定义属性 需要循环遍历给每一个标签绑定事件,执行效率低 如果页面重新动态渲染需要重新绑定事件
-
事件委托:
只是给父级一个标签绑定事件 执行效率高
给一直存在的父级标签绑定事件 不用动态生成 就再次绑定事件因为不能获取索引下标等数据 需要将数据以属性的形式定义在标签中
动态新增
<div name="add">
姓名: <input type="text" name="name"><br>
年龄: <input type="text" name="age"><br>
城市: <select>
<option value="0">北京</option>
<option value="1">上海</option>
<option value="2">广州</option>
<option value="3">重庆</option>
<option value="4">天津</option>
</select><br>
性别: <input type="radio" name="sex" value="男">男
<input type="radio" name="sex" value="女">女
<input type="radio" name="sex" value="保密">保密
<br>
<button>新增</button>
</div>
// 新增操作:
// 获取标签对象
var oAddDiv = document.querySelector('[name="add"]');
var oBtnAdd = oAddDiv.querySelector('button');
var oAddName = oAddDiv.querySelector('[name="name"]');
var oAddAge = oAddDiv.querySelector('[name="age"]');
var oAddCity = oAddDiv.querySelector('select');
var oAddSex = oAddDiv.querySelectorAll('[type="radio"]');
// 添加点击事件
oBtnAdd.addEventListener('click' , function(){
// 获取数据
var name = oAddName.value ;
var age = oAddAge.value ;
var city = oAddCity.value ;
// 定义变量准备存储 性别数据
var sex = '';
console.log( name , age , city );
// 循环遍历 单选框伪数组
oAddSex.forEach(function(item){
// item 就是 单选框标签
// 如果 item.checked 是 true
// 也就是这个标签被选中
// 获取这个标签的value数值
if( item.checked ){
// 获取 这个标签的value数据
sex = item.value;
}
})
// 向 数组 新增 对象单元
// id 是最后有一个单元的 id值 +1
// select的数据 是 数组通过索引下标获取的对应的数值
arr.push({id:arr[arr.length-1].id+1,name:name,age:age,sex:sex,addr:cityArr[city]});
console.log(arr);
// 再次调用函数 动态渲染生成页面
setPage();
})
新增数据
本质是 向数组新增数据单元 数据单元是以对象的形式存储的数据
根据新的数组 再次动态渲染生成页面
input标签
直接获取标签的value属性值
select 下拉类表框
因为 后端程序的需求 option标签value属性值设定为 索引下标
获取数据 通过 定义数组 使用索引下标 获取对应的具体数值
单选框 / 复选框
通过标签 checked 属性值 判断按个标签被选中
获取那个标签的数据
单选框复选框 不能 输入数据
必须要通过value属性 定义数据
获取所有的单选框 / 复选框
循环遍历伪数组
如果 标签 checked属性值是 true
证明这个标签被选中
获取这个标签的value数据
textarea
直接获取标签value数据
动态修改
<div class="change" name="change">
<div>
姓名: <input type="text" name="name"><br>
年龄: <input type="text" name="age"><br>
城市: <select>
<option value="0">北京</option>
<option value="1">上海</option>
<option value="2">广州</option>
<option value="3">重庆</option>
<option value="4">天津</option>
</select><br>
性别: <input type="radio" name="sex" value="男">男
<input type="radio" name="sex" value="女">女
<input type="radio" name="sex" value="保密">保密
<br>
<button name="c">修改</button>
<button name="q">取消</button>
</div>
</div>
.change{
width: 100%;
height: 100%;
background: rgba(0,0,0,.5);
position: fixed;
top:0;
left:0;
display: flex;
justify-content: center;
align-items: center;
display: none;
}
.change>div{
padding: 30px 20px;
height: 200px;
background: #fff;
}
// 修改操作
// 获取标签对象 修改标签对象
const oChangeDiv = document.querySelector('[name="change"]');
const oBtnChange = document.querySelector('[name="c"]');
const oBtnCancel = document.querySelector('[name="q"]');
const oChangeName = oChangeDiv.querySelector('[name="name"]');
const oChangeAge = oChangeDiv.querySelector('[name="age"]');
const oChangeCity = oChangeDiv.querySelector('select');
const oChangeSex = oChangeDiv.querySelectorAll('[type="radio"]');
// 删除操作 事件委托
// 修改操作 事件委托
var oTbody = document.querySelector('tbody');
oTbody.addEventListener('click' , function(e){
// 通过 e.target 的 name属性 判断 如果是del是删除按钮
if( e.target.getAttribute('name') === 'del' ){
// 执行删除程序
// 删除数组中 和 对应的删除按钮 匹配的数组中的数据
// 获取 删除对象单元的索引下标 也就是 标签中 index属性的属性值
// 获取的属性值 都是字符串类型 需要转化为数值类型
var num = e.target.getAttribute('index') - 0;
console.log( num );
// 用 index的属性值 作为 索引下标 从数组中删除一个对象
arr.splice( num , 1 );
console.log( arr );
// 再次调用函数 动态渲染生成页面
// 再次动态渲染生成的页面 内容是全新的页面内容
setPage();
// 通过 e.target 的 name属性 判断 如果是change是修改按钮
}else if( e.target.getAttribute('name') === 'change' ){
// 让 修改div显示
// 变量储存点击标签对应的数组的索引下标
oChangeDiv.style.display = 'flex';
// 变量 存储 点击标签index属性属性值
index = e.target.getAttribute('index') - 0;
}
})
// 修改div中的取消按钮
// 点击时 让 修改div隐藏
oBtnCancel.addEventListener('click' , function(){
oChangeDiv.style.display = 'none';
})
// 修改div中的修改按钮
// 获取数据
// 修改 索引下标对应的数组单元中,存储对象的数据
// 根据新的数组动态渲染生成页面
// 让修改div隐藏
oBtnChange.addEventListener('click' , function(){
// 获取数据
// input 直接获取数据
// select 获取索引下标 从数组中获取对应的数据
// input>radio input>checkbox 判断 checked为true 再获取数据
let name = oChangeName.value;
let age = oChangeAge.value;
let city = cityArr[ oChangeCity.value ];
let sex = '';
oChangeSex.forEach( function(item){
if( item.checked ){
sex = item.value;
}
})
// 修改数组中对应索引下标的标签对象
// 也就是 给 索引下标对应的单元 重新存储一个对象
// arr[index] = {id:arr[index].id,name:name,age:age,sex:sex,addr:city};
// 一个一个属性的修改数据
arr[index].name = name;
arr[index].age = age;
arr[index].sex = sex;
arr[index].addr = city;
// 根据新的数组动态渲染生成新的页面内容
setPage();
// 让修改div隐藏
oChangeDiv.style.display = 'none';
})
修改按钮业务逻辑
1, 点击 table标签的修改按钮
让 修改div 显示
存储 修改数据的 索引下标
2, 点击 修改div中 取消按钮
让 修改div 隐藏
3, 点击 修改div中 修改按钮
获取 当前 修改div 标签中存储的数据
修改 索引下标对应的数组单元的数据
根据新的数组动态渲染生成页面
让 修改div 隐藏
整体代码:
<!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;
}
table {
border-collapse: collapse;
margin: 50px 0 0 0;
}
td {
width: 100px;
height: 50px;
text-align: center;
border: 2px solid #000;
}
.change {
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .5);
position: fixed;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
display: none;
}
.change>div {
padding: 30px 20px;
height: 200px;
background: #fff;
}
</style>
</head>
<body>
<div name="add">
姓名: <input type="text" name="name"><br>
年龄: <input type="text" name="age"><br>
城市: <select>
<option value="0">北京</option>
<option value="1">上海</option>
<option value="2">广州</option>
<option value="3">重庆</option>
<option value="4">天津</option>
</select><br>
性别: <input type="radio" name="sex" value="男">男
<input type="radio" name="sex" value="女">女
<input type="radio" name="sex" value="保密">保密
<br>
<button>新增</button>
</div>
<div class="change" name="change">
<div>
姓名: <input type="text" name="name"><br>
年龄: <input type="text" name="age"><br>
城市: <select>
<option value="0">北京</option>
<option value="1">上海</option>
<option value="2">广州</option>
<option value="3">重庆</option>
<option value="4">天津</option>
</select><br>
性别: <input type="radio" name="sex" value="男">男
<input type="radio" name="sex" value="女">女
<input type="radio" name="sex" value="保密">保密
<br>
<button name="c">修改</button>
<button name="q">取消</button>
</div>
</div>
<table>
<thead>
<tr>
<td>序号</td>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>城市</td>
<td>删除</td>
<td>修改</td>
</tr>
</thead>
<tbody></tbody>
</table>
<script>
const arr = [{
id: 1,
name: '张三',
age: 18,
sex: '男',
addr: '北京'
},
{
id: 2,
name: '李四',
age: 19,
sex: '女',
addr: '上海'
},
{
id: 3,
name: '王五',
age: 20,
sex: '男',
addr: '广州'
},
{
id: 4,
name: '赵六',
age: 21,
sex: '女',
addr: '重庆'
},
{
id: 5,
name: '刘七',
age: 22,
sex: '男',
addr: '天津'
},
];
// 定义数组 存储城市名称信息
const cityArr = ['北京', '上海', '广州', '重庆', '天津'];
// 调用函数 生成 动态渲染 生成标签对象
setPage();
// 新增操作:
// 获取标签对象 新增标签对象
const oAddDiv = document.querySelector('[name="add"]');
const oBtnAdd = oAddDiv.querySelector('button');
const oAddName = oAddDiv.querySelector('[name="name"]');
const oAddAge = oAddDiv.querySelector('[name="age"]');
const oAddCity = oAddDiv.querySelector('select');
const oAddSex = oAddDiv.querySelectorAll('[type="radio"]');
// 修改操作
// 获取标签对象 修改标签对象
const oChangeDiv = document.querySelector('[name="change"]');
const oBtnChange = document.querySelector('[name="c"]');
const oBtnCancel = document.querySelector('[name="q"]');
const oChangeName = oChangeDiv.querySelector('[name="name"]');
const oChangeAge = oChangeDiv.querySelector('[name="age"]');
const oChangeCity = oChangeDiv.querySelector('select');
const oChangeSex = oChangeDiv.querySelectorAll('[type="radio"]');
// 定义变量 存储 索引下标
let index = 0;
// 添加点击事件
oBtnAdd.addEventListener('click', function () {
// 获取数据
var name = oAddName.value;
var age = oAddAge.value;
var city = oAddCity.value;
// 定义变量准备存储 性别数据
var sex = '';
console.log(name, age, city);
// 循环遍历 单选框伪数组
oAddSex.forEach(function (item) {
// item 就是 单选框标签
// 如果 item.checked 是 true
// 也就是这个标签被选中
// 获取这个标签的value数值
if (item.checked) {
// 获取 这个标签的value数据
sex = item.value;
}
})
// 向 数组 新增 对象单元
// id 是最后有一个单元的 id值 +1
// select的数据 是 数组通过索引下标获取的对应的数值
arr.push({
id: arr[arr.length - 1].id + 1,
name: name,
age: age,
sex: sex,
addr: cityArr[city]
});
console.log(arr);
// 再次调用函数 动态渲染生成页面
setPage();
})
// 删除操作 事件委托
// 修改操作 事件委托
var oTbody = document.querySelector('tbody');
oTbody.addEventListener('click', function (e) {
// 通过 e.target 的 name属性 判断 如果是del是删除按钮
if (e.target.getAttribute('name') === 'del') {
// 执行删除程序
// 删除数组中 和 对应的删除按钮 匹配的数组中的数据
// 获取 删除对象单元的索引下标 也就是 标签中 index属性的属性值
// 获取的属性值 都是字符串类型 需要转化为数值类型
var num = e.target.getAttribute('index') - 0;
console.log(num);
// 用 index的属性值 作为 索引下标 从数组中删除一个对象
arr.splice(num, 1);
console.log(arr);
// 再次调用函数 动态渲染生成页面
// 再次动态渲染生成的页面 内容是全新的页面内容
setPage();
// 通过 e.target 的 name属性 判断 如果是change是修改按钮
} else if (e.target.getAttribute('name') === 'change') {
// 让 修改div显示
// 变量储存点击标签对应的数组的索引下标
oChangeDiv.style.display = 'flex';
// 变量 存储 点击标签index属性属性值
index = e.target.getAttribute('index') - 0;
}
})
// 修改div中的取消按钮
// 点击时 让 修改div隐藏
oBtnCancel.addEventListener('click', function () {
oChangeDiv.style.display = 'none';
})
// 修改div中的修改按钮
// 获取数据
// 修改 索引下标对应的数组单元中,存储对象的数据
// 根据新的数组动态渲染生成页面
// 让修改div隐藏
oBtnChange.addEventListener('click', function () {
// 获取数据
// input 直接获取数据
// select 获取索引下标 从数组中获取对应的数据
// input>radio input>checkbox 判断 checked为true 再获取数据
let name = oChangeName.value;
let age = oChangeAge.value;
let city = cityArr[oChangeCity.value];
let sex = '';
oChangeSex.forEach(function (item) {
if (item.checked) {
sex = item.value;
}
})
// 修改数组中对应索引下标的标签对象
// 也就是 给 索引下标对应的单元 重新存储一个对象
// arr[index] = {id:arr[index].id,name:name,age:age,sex:sex,addr:city};
// 一个一个属性的修改数据
arr[index].name = name;
arr[index].age = age;
arr[index].sex = sex;
arr[index].addr = city;
// 根据新的数组动态渲染生成新的页面内容
setPage();
// 让修改div隐藏
oChangeDiv.style.display = 'none';
})
// 动态渲染生成页面的函数
function setPage() {
// 定义字符串 存储 生成的标签内容
var str = '';
// 循环遍历 数组 每一个数组单元存储数据 生成一个对应的 tr>td
// item 就是 存储数据的对象
// key 存储 对象的索引下标
arr.forEach(function (item, key) {
str += `
<tr>
<td>${item.id}</td>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.sex}</td>
<td>${item.addr}</td>
<td><button name="del" index="${key}">删除</button></td>
<td><button name="change" index="${key}">修改</button></td>
</tr>
`;
})
// 将字符串写入到标签对象中
var oTbody = document.querySelector('tbody');
oTbody.innerHTML = str;
}
</script>
</body>
</html>