JS小案例:表格编辑简单版

代码:

<html>
	<head>
		<meta charset="utf-8">
		<title>无标题文档</title>
		<style>
			*{ margin:0; padding:0; font-size:14px}
			#box{ width:600px; margin:100px auto; table-layout: fixed;}
			table,th,td{ border:1px solid #000; border-collapse:collapse}
			td,th{ width:100px; height:46px; padding:10px}
			input[type="text"]{ display:none; height:24px; width:60px; border:1px solid #ccc;}
			tbody tr td{text-align: center;}
			tfoot td{text-align: right;}
			.editBtn{ color:#666}
			.delBtn{ color:red}
			.sureBtn,.cancelBtn{ display:none}
			.edit span{ display:none}
			.edit input[type="text"]{ display:inline-block}
			.edit .editBtn,.edit .delBtn{ display:none}
			.edit .sureBtn,.edit .cancelBtn{ display:inline}
		</style>
	</head>

	<body>
		<div>
			<table id="box">
				<thead>
					<tr>
						<th>
							<label>全选:<input type="checkbox" id="allCheck" class="allCheck"/></label><br>
						</th>
						<th>名称</th>
						<th>单价</th>
						<th>数量</th>
						<th>小计</th>
						<th>处理</th>
					</tr>
				</thead>
				<tbody></tbody>
				<tfoot>
					<tr>
						<td colspan="6">总价:¥<b id="moneyContainer"></b></td>
					</tr>
				</tfoot>
		   </table>
		</div>
		<script>
			class Cart {
				constructor(selector) {
					this.container = document.querySelector(selector);
					this.tbody = this.container.querySelector("tbody");
					this.allCheck = this.container.querySelector("#allCheck"); // 全选按钮
					this.reCheck = this.container.querySelector("#reCheck"); // 反选按钮
					this.moneyContainer = this.container.querySelector("#moneyContainer"); // 放总价的容器
					this.check = null; // 先声明所有的单选按钮集合,render()中渲染后查找
					this.n = 0; //记录单选个数
					this.allMoney = 0; // 记录总价
					this.json = [
						{"name" : "辣条", "price" : 10, "num" : 1},
						{"name" : "棒棒糖", "price" : 20, "num" : 1},
						{"name" : "跳跳糖", "price" : 15, "num" : 1},
						{"name" : "泡泡糖", "price" : 2, "num" : 1}
					];
					this.render(); // 渲染
					this.calcMoney(); // 计算总价
				}
				// 将JSON通过字符串模板渲染表格
				render () {
					let formwork = "";
					this.json.forEach(item => {
						formwork += `
						<tr>
							<td><input type="checkbox" class="check"/></td>
							<td>${item.name}</td>
							<td>${item.price}</td>
							<td><span>${item.num}</span><input type="text"></td>
							<td>${item.price * item.num}</td>
							<td>
								<a href="javascript:;" class="editBtn">编辑</a>
								<a href="javascript:;" class="sureBtn">确定</a>
								<a href="javascript:;" class="cancelBtn">取消</a>
								<a href="javascript:;" class="delBtn">删除</a>
							</td>
						</tr>`;
					});
					this.tbody.innerHTML = formwork;
					this.check = Array.from(this.tbody.querySelectorAll(".check"));
					this.bindEvents(); // 执行绑事件
				}
				// 绑事件
				bindEvents () {
					this.tbody.onclick = e => {
						e = e||window.event;
						let target = e.target||e.srcElement;
						let tr = target.parentNode.parentNode; // 找到点击事件所在的tr,作为实参传递
						switch(target.className) {
							case "editBtn" : this.editBtnClick(tr); break;
							case "sureBtn" : this.sureBtnClick(tr); break;
							case "cancelBtn" : this.cancelBtnClick(tr); break;
							case "delBtn" : this.delBtnClick(tr); break;
						} // 事件委托,this指向事件对象table
					}
					this.check.forEach(check => {
						check.onchange = this.checkChange.bind(this,check); // bind()改变指向,并且将事件对象作为实参传递
						// check.onchange = () => {this.checkChange(check);} // 箭头函数也可以完成
					})// 给所有的单选按钮绑事件。不改变指向,this会指向事件对象,需要改变指向table(认清与上面事件委托的区别)
					
					this.allCheck.onchange = this.allCheckChange.bind(this); //给全选按钮绑事件
				}
				checkChange (check) {
					// console.log(this);
					this.n += check.checked ? 1 : -1;
					allCheck.checked = this.n == this.check.length;
					this.calcMoney(); // 每次选择后计算总价
				}
				
				
				//难点。对上面代码的总结:
				//必须传参
				//不能在点击事件找到对象环境
				//不能在对象环境找到点击事件
				
				
				allCheckChange(){
					// console.log(this);
					this.check.forEach(item=>{
						item.checked = this.allCheck.checked;
					})
					this.n=this.allCheck.checked?this.check.length:0;
					this.calcMoney(); // 每次选择后计算总价
				}
				editBtnClick (tr) {
					tr.classList.add("edit"); // 添加class名,进入编辑模式
					let span = tr.querySelector("span");
					span.nextElementSibling.value = span.innerHTML; // 提取
				}
				sureBtnClick (tr) {
					let span = tr.querySelector("span");
					span.innerHTML = span.nextElementSibling.value; // 替换
					let td = Array.from(tr.querySelectorAll("td"));
					td[4].innerHTML = span.innerHTML * td[2].innerHTML;// 每次修改后修改小结
					tr.classList.remove("edit"); // 替换后移除class名,退出编辑模式
					this.calcMoney();// 每次修改后计算总价
				}
				cancelBtnClick (tr) {tr.classList.remove("edit");}
				delBtnClick (tr) {
					let shopName = tr.querySelectorAll("td")[1].innerHTML;
					if(confirm(`确认不要${shopName}了吗?`)){
						tr.remove();
						this.n=0;
						this.check = Array.from(this.tbody.querySelectorAll(".check"));
						this.check.forEach(check=>{if(check.checked) this.n++;}) // 每次删除后计算n
					}
					this.allCheck.checked = this.n===this.check.length;
					this.calcMoney(); // 每次删除后计算总价
				}
				calcMoney () {
					// console.log(this);
					console.log(this.n);
					this.allMoney = 0; // 每次重置为0,从头算
					Array.from(this.tbody.children).forEach(tr => { // 找到所有的tr
						if(tr.querySelector(".check").checked){
							this.allMoney += Number(tr.querySelectorAll("td")[4].innerHTML);
						} // 判断当前商品是否选中,选中的累加
					})
					this.moneyContainer.innerHTML = this.allMoney;
				}
			}
			new Cart("#box");
		</script>
	</body>
</html>

效果图:
JS小案例:表格编辑简单版

猜你喜欢

转载自blog.csdn.net/PrisonersDilemma/article/details/89364685
今日推荐