简单商品价格管理表

引言

本文将结合 HTML、CSS 和 JavaScript 的代码,详细介绍如何构建一个具备商品添加、编辑、删除以及数量增减功能的表格,同时实现操作提示框的动态显示。

整体功能

  1. 从 JSON 文件中获取商品数据并渲染到表格中。
  2. 支持对商品的数量进行增减操作,实时更新总价和总数量。
  3. 可以添加新的商品,同时对输入进行合法性验证。
  4. 能够编辑和删除已有的商品信息。
  5. 操作成功或失败时,会弹出相应的提示框。

效果展示

 

HTML 结构

<!-- 提示框的底板
			提示的内容是不固定的,调用的时候往在里传-->
		<div class="alertCenter">
			<!-- 操作成功提示框,初始为隐藏状态 -->
			<div id="bigAlert" style="display:none;">
				<div class="alertContent">
					<img src="./img/对勾.png" alt="" />
					<span id="alertMessage"></span>
				</div>
			</div>
			<!-- 操作成功提示框,初始为隐藏状态 -->
			<div id="bigAlertErrorName" style="display: none;">
				<div class=" alertContentError">
					<img src="./img/叉号.png" alt="" />
					<span 6+6+id="alertMessage"></span>
				</div>
			</div>
		</div>

		<!-- 页面上的表格 -->
		<table id="productTable">
			<!-- 表格的头部区域 -->
			<thead>
				<tr>
					<th>商品名称</th>
					<th class="price">价格</th>
					<th>数量</th>
					<th>操作</th>
				</tr>
			</thead>

			<!-- 表格的内容区域 ,后续通过数据渲染动态添加-->
			<tbody></tbody>

			<!-- 表格的底部内容 -->
			<tfoot>
				<tr>
					<td>总价:</td>
					<td id="totalPrice">0</td>
					<td>总数量:</td>
					<td id="totalNumber">0</td>
				</tr>
			</tfoot>
		</table>
		<!-- 添加按钮 -->
		<button class="addBtn" onclick="editAddBtn(0,1)">添加</button>

		<!-- 添加商品和编辑商品的区域是一样的 ,但是需要重新写一个新的数据,
								为了避免点击的时候触发的不是想要的效果(点的时候和不知道是添加商品还是编辑商品) -->
		<!-- 添加新商品的输入框区域
				开始的时候是隐藏的-->
		<div class="hiddenText" style="display: none;">
			<input type="text" id="productName" placeholder="商品名称">
			<input type="text" id="productPrice" placeholder="商品价格">
			<input type="text" id="productNum" placeholder="商品数量">
			<button id="saveBtnChange" onclick="saveBtn(2)">保存</button>
			<button id="cancelBtn"
				onclick="document.getElementsByClassName('hiddenText')[0].style.display = 'none';">取消</button>
		</div>

		<!-- 编辑商品的输入框区域
				开始的时候是隐藏的-->
		<div class="hiddenTextChange" style="display: none;">
			<input type="text" id="productNameChange" placeholder="商品名称">
			<input type="text" id="productPriceChange" placeholder="商品价格">
			<input type="text" id="productNumChange" placeholder="商品数量">
			<button id="saveBtnChange" onclick="saveBtn(1)">保存</button>
			<button id="cancelBtnChange"
				onclick="document.getElementsByClassName('hiddenTextChange')[0].style.display = 'none';">取消</button>
		</div>

JS部分

1.变量声明

data:用于存储从 ./js/shopCarAbout.json 文件中获取并解析后的 JSON 数据。

maxId:记录商品数据中最大的 id 值,后续添加新商品时会基于此生成新的 id

productId:用于存储当前操作(编辑或删除)的商品的 id

// 存放解析后的 JSON 格式数据
			let data;
			//商品数据中最大的 id 值
			let maxId;
			// 商品的对应id(每一行的),后续通过商品的id能准确的删除对应的商品
			let productId;

2.数据请求 

XMLHttpRequest 是一个用于在浏览器和服务器之间进行异步通信的对象。

xhr.open('get', './js/shopCarAbout.json', true):使用 GET 请求方式从指定路径获取 JSON 数据,true 表示异步请求。

xhr.send():发送请求。

xhr.onreadystatechange:当请求的状态发生变化时触发该回调函数。

xhr.readyState == 4 && xhr.status == 200readyState 为 4 表示请求已完成,status 为 200 表示请求成功。

data = JSON.parse(text):将响应的文本数据解析为 JSON 对象并存储在 data 变量中。

maxId = data[data.length - 1].id:获取当前数据中最大的 id 值。

render(data):调用 render 函数将解析后的数据渲染到页面上。

let xhr = new XMLHttpRequest();
			xhr.open('get', './js/shopCarAbout.json', true);
			xhr.send();
			xhr.onreadystatechange = function() {
				if (xhr.readyState == 4 && xhr.status == 200) {
					let text = xhr.responseText;
					data = JSON.parse(text);
					maxId = data[data.length - 1].id;
					console.log(maxId);
					render(data); // 数据加载成功后渲染页面
					console.log(data);
				}
			};

3.数据渲染函数

str:用于拼接要插入到表格中的 HTML 字符串。

totalPrice:用于计算商品的总价。

totalNumber:用于计算商品的总数量。

通过 for...in 循环遍历 data 数组,计算每个商品的总价和总数量,并将其累加到 totalPrice 和 totalNumber 中。

拼接每一行商品的 HTML 代码,包含商品名称、价格、数量增减按钮、编辑和删除按钮,并为按钮绑定相应的点击事件。document.getElementById('productTable').getElementsByTagName('tbody')[0].innerHTML = str:将拼接好的 HTML 字符串插入到表格的 tbody 中。

upData(totalPrice, totalNumber):调用 upData 函数更新页面上显示的总价和总数量。

// 数据渲染函数,将商品数据渲染到表格中,并更新总价和总数量显示
function render(data) {
    // 创一个空字符串,用于后面拼接字符串(渲染到页面上的)
    let str = "";
    // 商品的总价(后续会实时变化的)
    let totalPrice = 0;
    // 商品的数量总和(后续会实时变化的)
    let totalNumber = 0;
    // 通过循环 data 计算出总价和总数量
    for (let i in data) {
        // 总价=总数×价格
        totalPrice += data[i].number * data[i].price;
        // 总数=data 的下标(*1 是为了避免,总数在页面上是拼接的的形式出现)
        totalNumber += data[i].number * 1;
        str += `<tr>
                <td>${data[i].name}</td>
                <td>${data[i].price}</td>
                <td>
                    <button class="jian" onclick="actionBtn(${i},2)">-</button>
                    <span class="num">${data[i].number}</span>
                    <button class="jia" onclick="actionBtn(${i},1)">+</button>
                </td>
                <td>
                    <button class="changeBtn" onclick="editAddBtn(${i},2)">编辑</button>
                    <button class="deleteBtn" onclick="actionBtn(${i},3)">删除</button>
                </td>
            </tr>`;
    }
    // 将拼接好的 str 赋值给 productTable 表格 tbody 元素的 innerHTML 属性,实现将商品数据行渲染到表格中
    document.getElementById('productTable').getElementsByTagName('tbody')[0].innerHTML = str;
    // 传参计算好的总价和总数量,更新页面上的内容
    upData(totalPrice, totalNumber);
}

4.更新数据函数

函数接受 totalPrice 和 totalNumber 作为参数,通过 document.getElementById 方法获取页面上显示总价和总数量的元素,并使用 textContent 属性更新内容。

// 更新总价和总数量的函数
// 接受传来的参数
function upData(totalPrice, totalNumber) {
    // 获取页面上 totalPrice 和 totalNumber 的元素(显示总价和总数量的单元格)
    // 使用 textContent 属性将传入写进去,实现更新页面上显示的总价和总数量的功能。
    document.getElementById('totalPrice').textContent = totalPrice;
    document.getElementById('totalNumber').textContent = totalNumber;
}

5.加减删除按钮函数 

index:表示要操作的商品在 data 数组中的下标。

type:表示操作类型,1 表示增加数量,2 表示减少数量,3 表示删除商品。

当 type 为 1 时,将对应商品的 number 属性加 1。当 type 为 2 时,若对应商品的 number 大于 0,则将其减 1。

当 type 为 3 时,使用 splice 方法从 data 数组中删除对应商品,并调用 showAlert 函数显示删除成功的提示框。

无论执行哪种操作,最后都调用 render 函数重新渲染页面,更新表格内容和总价、总数量。

// 加减删除按钮的函数 (合并过 ok)
// (index 是自己取的名字。这里的 index 是形参,接受参数的,
// 上面拼接字符串里面的 这个函数的点击事件传参了一个下标 i(这个 i 是是会更新的点哪个 下标就是对应的))
function actionBtn(index, type) {
    // 通过下标将对应的数据增加 1
    if (type == 1) {
        console.log(data);
        // data 现在是一个数组包对象(json 的数据)的形式出现的,index 是上面传来的下标 i(点哪个就是哪条商品的下标).点是访问这条商品对象中的的 number 值
        data[index].number++;
    } else if (type == 2) {
        if (data[index].number > 0) {
            // 通过下标将对应的数据减 1
            data[index].number--;
        }
    } else if (type == 3) {
        data.splice(index, 1);
        // render(data);
        console.log(document.getElementById('bigAlert'));
        showAlert('删除成功', document.getElementById('bigAlert'));
    }
    // 调用渲染函数让页面更新
    render(data);
}

6.编辑新增的保存按钮事件

type:表示操作类型,1 表示编辑商品,2 表示添加商品。

编辑商品逻辑(type == 1:获取编辑输入框中的值,并进行合法性验证,若验证不通过则调用 showAlert 函数显示错误提示框并返回。遍历 data 数组,找到要编辑的商品并更新其信息。隐藏编辑输入框区域,重新渲染页面,并显示编辑成功的提示框。

添加商品逻辑(type == 2:获取添加输入框中的值,并进行合法性验证,若验证不通过则调用 showAlert 函数显示错误提示框并返回。创建一个新的商品对象,包含商品名称、价格、数量和新的 id。将新商品对象添加到 data 数组中,隐藏添加输入框区域,重新渲染页面,并显示添加成功的提示框。

// 编辑/新增的保存按钮点击事件(功能已合并 ok)
function saveBtn(type) {
    if (type == 1) {
        // 获取输入框修改后的值,并去除两端空白字符,得到有效的输入内容
        let productName = document.getElementById('productNameChange').value.trim();
        let productPrice = document.getElementById('productPriceChange').value.trim();
        let productNum = document.getElementById('productNumChange').value.trim();

        // 验证商品名不能为空
        if (productName === "") {
            showAlert('商品名不能为空', document.getElementById('bigAlertErrorName'));
            return;
        }

        // 验证价格是否为数字
        if (isNaN(productPrice)) {
            showAlert('请输入合法的数字', document.getElementById('bigAlertErrorName'));
            return;
        }

        // 验证数量是否为合法数字
        if (productNum % 1 !== 0) {
            showAlert('请输入整数数量', document.getElementById('bigAlertErrorName'));
            return;
        }

        // 遍历整个 data 数组,通过比较商品的唯一 id 找到当前正在编辑的商品的对应的数据
        //(这样是为了知道正在编辑哪条数据,并且是唯一的 不会出错)
        for (let i in data) {
            // 如果被编辑的商品 id 等于 data 数据里的 id
            if (data[i].id == productId) {
                // 就把编辑好的数据赋给 data 里的数据
                data[i].name = productName;
                data[i].price = productPrice;
                data[i].number = productNum;
            }
        }
        // 把编辑输入框区域隐藏
        document.getElementsByClassName('hiddenTextChange')[0].style.display = 'none';
        // 重新渲染页面,更新展示信息
        render(data);
        // 调用 showAlert 显示操作成功提示框,传递提示文字消息,和对应的提示框元素(操作成功提示框)
        showAlert('编辑成功', document.getElementById('bigAlert'));
    } else if (type == 2) {
        // 获取该输入框中用户输入的值
        let productName = document.getElementById('productName').value;
        let productPrice = document.getElementById('productPrice').value;
        let productNum = document.getElementById('productNum').value;

        // 商品名不能为空
        if (productName === "") {
            showAlert('商品名不能为空', document.getElementById('bigAlertErrorName'));
            return;
        }

        // 验证价格是否为数字
        if (isNaN(productPrice)) {
            showAlert('请输入合法的数字', document.getElementById('bigAlertErrorName'));
            return;
        }

        // 验证数量是否为合法数字
        if (productNum % 1 !== 0) {
            showAlert('请输入整数数量', document.getElementById('bigAlertErrorName'));
            return;
        }

        // 要添加的新商品
        let newProduct = {
            name: productName,
            // 价格可能是小数
            price: parseFloat(productPrice),
            // 数量是整数
            number: parseInt(productNum),
            id: ++maxId
        };

        // 把新的商品插入到 data 里
        data.push(newProduct);
        // 重新渲染页面
        // 隐藏添加输入框区域
        // cancelBtn();
        // 显示操作成功提示框
        showAlert('添加成功', document.getElementById('bigAlert'));
    }
    render(data);
}

7.编辑和新增按钮函数

index:表示要编辑的商品在 data 数组中的下标。type:表示操作类型,1 表示新增商品,2 表示编辑商品。

新增商品逻辑(type == 1:显示新增商品的输入框区域,并清空输入框中的内容。

编辑商品逻辑(type == 2:获取要编辑的商品的 id,并将该商品的信息显示在编辑输入框中。显示编辑商品的输入框区域。

// 编辑和新增按钮的函数(已合并)
function editAddBtn(index, type) {
    if (type == 1) {
        // 新增按钮的函数没反应,但是把上面的 index 删了就可以了,但是编辑就不好用了(解决了 给没有下标的调用传一个 0 就行(0.1))
        // 点击按钮后把隐藏起来的内容显示出来
        document.getElementsByClassName('hiddenText')[0].style.display = 'block';
        // 清空上一次输入的值(令他们为空的 字符串)
        let productName = document.getElementById('productName');
        let productPrice = document.getElementById('productPrice');
        let productNum = document.getElementById('productNum');
        productName.value = "";
        productPrice.value = "";
        productNum.value = "";
    } else if (type == 2) {
        // 获取当前编辑商品在 data 数组中对应的 id
        productId = data[index].id;
        // 把当前被编辑商品的内容显示在框里(方便用户在原基础上更改)
        document.getElementById('productNameChange').value = data[index].name;
        document.getElementById('productPriceChange').value = data[index].price;
        document.getElementById('productNumChange').value = data[index].number;
        // 把框显示出来,让用户能看到,方便编辑
        document.getElementsByClassName('hiddenTextChange')[0].style.display = 'block';
    }
}

8.操作提示框

message:要显示的提示信息。element:提示框的 DOM 元素。

逻辑说明:将提示信息插入到提示框的 span 元素中。显示提示框。使用 setTimeout 函数在 1.5 秒后隐藏提示框。

// 操作成功提示框的函数
function showAlert(message, element) {
    let spanElement = element.children[0].children[1];
    spanElement.innerHTML = `
        ${message}
    `;
    element.style.display = 'block';
    setTimeout(function() {
        element.style.display = 'none';
    }, 1500);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值