一.css部分
二.html部分
三.js部分(四的三的详解)
<!-- js -->
<script>
const arr=[
{name:"你好",age:6,sex:"女",city:"上海"},
{name:"好啊",age:7,sex:"男",city:"云南"},
{name:"wuwu",age:7,sex:"男",city:"成都"},
{name:"嘿哈",age:7,sex:"男",city:"厦门"},
{name:"兮兮",age:7,sex:"女",city:"香港"}
];
const oTabBox=document.querySelector('[name="tabBox"]');
function CreateSetTableObj(array,ele){
this.array=array;
this.ele=ele;
this.tbody=ele.querySelector('tbody');
this.oIptName=ele.querySelector('[type="text"]');
this.oIptAge=ele.querySelector('[type="number"]');
this.oIptCity=ele.querySelector('select');
this.oIptSex=ele.querySelectorAll('[type="radio"]');
}
CreateSetTableObj.prototype.createTbd=function(){
let str="";
this.array.forEach((val,key) => {
str+='<tr>';
str+=`<td>${key+1}</td>`;
for(let k in val){
str+=`<td>${val[k]}</td>`;
}
str+=`<td><button name="del" index="${key}">删除</button></td>`;
str+='</tr>';
});
this.tbody.innerHTML=str;
}
CreateSetTableObj.prototype.setClick=function(){
this.ele.addEventListener('click',e=>{
if(e.target.getAttribute('name')=='add'){
let oIptNameVal=this.oIptName.value;
let oIptAgeVal=this.oIptAge.value;
let oIptCityVal=this.oIptCity.value;
let oIptSexVal=0;
this.oIptSex.forEach(function(val,key){
if(val.checked==true){
oIptSexVal=val.value;
}
});
const obj={
name:oIptNameVal,
Age:oIptAgeVal,
sex:oIptSexVal,
city:oIptCityVal
};
this.array.push(obj);
this.createTbd();
}else if(e.target.getAttribute('name')=='del'){
let index=e.target.getAttribute('index');
this.array.splice(index,1);
this.createTbd();
}
});
}
const obj=new CreateSetTableObj(arr,oTabBox);
obj.createTbd();
obj.setClick();
</script>
四.js部分详解
<script>
/*
// 面向过程
var arr = [
{name:'张三',age:18,sex:'男',city:'北京'},
{name:'李四',age:19,sex:'女',city:'上海'},
{name:'王五',age:20,sex:'男',city:'广州'},
{name:'赵六',age:21,sex:'女',city:'重庆'},
{name:'刘七',age:22,sex:'保密',city:'天津'},
];
var oTb = document.querySelector('tbody');
var oBtnAdd = document.querySelector('[name="add"]');
setTab();
// 新增数据操作
oBtnAdd.onclick = function(){
var oIptName = document.querySelector('[type="text"]').value;
var oIptAge = document.querySelector('[type="number"]').value;
var oIptCity = document.querySelector('select').value;
var oIptSex = document.querySelectorAll('[type="radio"]');
var oIptSexValue = 0;
oIptSex.forEach(function(item){
if(item.checked === true){
oIptSexValue = item.value;
}
})
var obj = {
name:oIptName,
age:oIptAge,
sex:oIptSexValue,
city:oIptCity,
}
arr.push(obj);
setTab();
}
function setTab(){
var str = '';
arr.forEach(function(item , key){
str += '<tr>';
str += `<td>${key+1}</td>`;
for(var k in item){
str += `<td>${item[k]}</td>`;
}
str += `<td><button index="${key}">删除</button></td>`;
str += '</tr>';
})
oTb.innerHTML = str;
}
oTb.onclick = function(e){
e = e || window.event;
var eTag = e.target || e.srcElement;
if(eTag.tagName == 'BUTTON'){
var index = eTag.getAttribute('index');
arr.splice(index , 1);
setTab();
}
}
*/
// 面向对象和面向过程
// 从面向过程,改造成面向对象
// 1,获取的数据,标签对象,要以参数的形式,定义给构造函数和实例化对象
// 获取标签对象时,一般获取父级,传参父级,在构造函数中,通过父级标签,获取子级标签独享
// 2,必须非常非常非常注意 this的指向,一般在面向对象中 都是使用箭头函数
// 如果万一不能清楚地知道this指向,可以先输出 this
// 3,其他步骤和思路基本相同,没有区别
// 总结:
// 1,改不改箭头函数,看内部是否需要 指向实例化对象的this
// 如果需要,可以改箭头函数,或者是提前存储this指向
// 如果不许需要,改不改箭头函数都行
// 一切以实现程序为最终需求,程序能执行就可以
// 2,之前面向过程的是参数,数据等,
// 现在是面向对象编程,要在对象的属性中,定义参数数据
// 也就是通过 构造函数 this.属性 = 属性值 语法来定义需要获取的参数数据
// 3,定义在构造函数方法中的一些变量数据,并不是定义在实例化对象中的属性
// 没有必须写成 this.属性 = 属性值 的形式
// 只要写成普通的变量定义即可
// 使用时,也是直接使用变量,不需要添加this
// 4,在构造函数的方法中,调用其他的函数方法
// 语法形式 应该是 实例化对象.函数方法名称()
// 在构造函数中,使用this来指向实例化对象,写成 this.函数方法名称()
// 本地定义的数组
const arr = [
{ name: '张三', age: 18, sex: '男', city: '北京' },
{ name: '李四', age: 19, sex: '女', city: '上海' },
{ name: '王五', age: 20, sex: '男', city: '广州' },
{ name: '赵六', age: 21, sex: '女', city: '重庆' },
{ name: '刘七', age: 22, sex: '保密', city: '天津' },
];
// 获取父级标签,传参也是父级标签,在构造函数中,通过这个父级标签,获取子级标签对象
const oTabBox = document.querySelector('[name="tabBox"]');
// 创建构造函数
// 参数1: 数组,也就是生成table表格的内容
// 参数2: 标签对象,父级标签对象
function CreateSetTableObj(array, ele) {
// 在构造函数中,定义需要的数据
// 定义属性,存储参数,为了在方法函数中,可以使用参数
// 在方法函数中,调用参数,不能直接调用,必须是this.属性 = 参数,赋值之后,通过this.属性调用
this.array = array;
this.ele = ele;
// 获取标签对象,tbody,写入内容的标签对象
this.tbody = ele.querySelector('tbody');
// 获取数据的input等标签
// 在构造函数中,可以直接使用 ele 的
// 获取输入姓名的标签
this.oIptName = ele.querySelector('[type="text"]');
// 获取输入年龄的标签
this.oIptAge = ele.querySelector('[type="number"]');
// 获取下拉列表框,选择城市标签
this.oIptCity = ele.querySelector('select');
// 获取所有的单选标签,结果是一个伪数组
this.oIptSex = ele.querySelectorAll('[type="radio"]');
}
// 定义方法,创建td标签,生成页面内容
// 就是之前面向过程的程序,将颞部的函数,如果有必要,改成箭头函数
CreateSetTableObj.prototype.createTd = function () {
let str = '';
// 将普通函数,改为箭头函数
// 将arr变量,改为 this.arr 属性获取数据
// 不改箭头函数,this指向不是实例化对象,this.arr , this.tbody就有可能使用出现问题
// 也可以先将 this 存储,使用存储的this(这是如果不改成箭头函数的话)
// 此处, this.arr , this.tbody 没有写在 forEach中,不改成箭头函数也可以,对当前的程序没有影响
// 但是为了确保如果使用this,可以正确执行,最好是改成箭头函数
this.array.forEach((item, key) => {
// forEach中没有用到this,可以不改成箭头函数
// 最好写成箭头函数,方便使用
str += '<tr>';
str += `<td>${key + 1}</td>`;
for (var k in item) {
str += `<td>${item[k]}</td>`;
}
str += `<td><button name="del" index="${key}">删除</button></td>`;
str += '</tr>';
})
// oTb 改为 this.tbody 属性获取数据
this.tbody.innerHTML = str;
}
// 通过事件委托方式,给添加和删除按钮,定义点击事件
CreateSetTableObj.prototype.setClick = function () {
// 给最外层的div标签,添加点击事件,通过点击的目标,判断点的是哪个标签
// 父级div是定义构造函数时,传递的参数,使用this.ele来存储
// 这里要改成箭头函数,因为要使用this
this.ele.addEventListener('click', (e) => {
// 如果点击标签name属性值是add,点击的是添加按钮
if (e.target.getAttribute('name') == 'add') {
// 获取数据
// 生成对象
// 对象写入数组
// 根据新的数组,冲洗渲染页面
// 点击时,才获取对应的数据
// 姓名
let oIptNameVal = this.oIptName.value;
// 年龄
let oIptAgeVal = this.oIptAge.value;
// 城市
let oIptCityVal = this.oIptCity.value;
// 也可以不在属性中定义标签对象,在此处,直接获取标签中的数据
// let oIptNameVal = this.ele.querySelector('[type="text"]').value;
// 获取性别标签的伪数组,
// 循环遍历,如果是选中状态,获取其中的数据
// 建立一个变量存储数据结果
let oIptSexValue = 0;
// 循环遍历, this.oIptSex 存储单选的伪数组
// 此处循环中,没有使用this,改不改箭头函数都行
this.oIptSex.forEach(function (item) {
if (item.checked === true) {
oIptSexValue = item.value;
}
})
// 将获取的数据,写入到对象中
const obj = {
name: oIptNameVal,
age: oIptAgeVal,
sex: oIptSexValue,
city: oIptCityVal,
}
// 将对象新增,写入数组中
this.array.push(obj);
// 根据新的数组,调用函数方法,渲染生成新的页面
this.createTd();
// 如果点击标签name属性值是del,点击的是删除按钮
} else if (e.target.getAttribute('name') == 'del') {
// 获取点击标签,index属性的属性值
// 根据属性值,从数组中删除单元
// 再根据新数组,代用函数,重新生成页面
// 获取点击标签,index属性值
let index = e.target.getAttribute('index');
// 用属性值对应的索引下标,删除数组中的单元
this.array.splice(index, 1);
// 重新调用函数方法,来重新渲染页面
// 在构造函数内部,调用已经定义的函数方法
// 应该是 实例化对象.函数方法名称()
// 现在 this 指向的是 实例化对象,我们就使用this来替换
this.createTd();
}
})
}
// 创建实例化对象,输入参数
// 参数1,根据执行的数组
// 参数2,父级div标签对象
const setTabObj = new CreateSetTableObj(arr, oTabBox);
// 调用方法,创建td标签,生成页面内鹅绒
setTabObj.createTd();
setTabObj.setClick();
</script>