javascript - 为什么按价格排序不起作用?
问题描述
在该sortProductsByPrice (sortOrder)
方法中,当我删除或添加新产品时,排序不起作用this.products
,默认情况下排序仅对数组中的产品起作用。
(产品按点击排序<th> Price: </ th>
)。
搬出/加货后也需要分拣也可以使用。
//Product Creation Class
class Product {
constructor(name, count, price) {
this.name = name;
this.count = count;
this.price = price;
}
}
Product.SORT_ORDER_ASC = 1;
Product.SORT_ORDER_DESC = -1;
// Сlass where products are recorded
class Shop {
constructor() {
this.products = [];
}
//method for adding a product
addProduct(newProduct) {
this.products.push(newProduct);
}
//method for remove product by name
deleteProductByName(productName) {
let i = this.products.length;
while (i--) {
if (productName === this.products[i].name) {
this.products.splice(i, 1);
}
}
}
// get total price by all products
get totalProductsPrice() {
return this.products.map(product => product.price).reduce((p, c) => p + c);
}
//method for sorting the product at its price
sortProductsByPrice(sortOrder) {
const sorted = this.products.sort((a, b) => {
return a.price > b.price ? sortOrder : -sortOrder;
});
this.products = sorted;
}
// method to draw the table with product property (
// name, count, price)
show() {
const formAdd = document.forms[0];
const inputsAdd = formAdd.elements;
const buttAdd = formAdd.elements[3];
const formDelete = document.forms[1];
const nameDelete = formDelete.elements[0];
const buttDelete = formDelete.elements[1];
const priceFilter = document.getElementById("filter");
// add new product by click
buttAdd.addEventListener('click', (e) => {
e.preventDefault();
shop.addProduct(new Product(inputsAdd[0].value, parseInt(inputsAdd[2].value),
parseInt(inputsAdd[1].value)));
shop.show();
}, false);
// delete product by name after click
buttDelete.addEventListener('click', (e) => {
e.preventDefault();
shop.deleteProductByName(nameDelete.value);
shop.show();
}, false);
const rows = document.querySelectorAll("#shop .data");
for (let i = rows.length - 1; i >= 0; i--) {
const e = rows.item(i);
e.parentNode.removeChild(e);
}
const table = document.getElementById("shop");
const tFoot = table.querySelector('tfoot');
if (tFoot) tFoot.remove();
for (let i = 0; i < this.products.length; i++) {
//create table
table.innerHTML += `<tbody><tr class="data"><td>${this.products[i].name}</td>
<td>${this.products[i].price}</td>
<td>${this.products[i].count}</td></tr></tbody>`;
}
//show total price by all products
table.innerHTML += `<tfoot><tr><td colspan="3" id="total-price">Total price:
${shop.totalProductsPrice}</td></tr></tfoot>`;
priceFilter.addEventListener("click", (e) => {
shop.sortProductsByPrice(Product.SORT_ORDER_ASC);
shop.show();
}, false);
}
}
let shop = new Shop();
shop.addProduct(new Product("product", 1, 2000));
shop.addProduct(new Product("product1", 2, 500));
shop.addProduct(new Product("product2", 3, 1000));
shop.show();
console.log(shop.products);
<div class="Shop">
<div class="add-product">
<h1>Add product</h1>
<form id="addForm">
<label for="name" >Name of product</label>
<input type="text" id="name" class="input-product">
<label for="price">Price of product</label>
<input type="text" id="price" class="input-product">
<label for="count">Count of product</label>
<input type="text" id="count" class="input-product">
<button id="add">Add</button>
</form>
</div>
<div class="product-table">
<h2>Products</h2>
<form id="delete-form">
<label for="name-delete">Delete product by name</label>
<input type="text" id="name-delete" class="input-delete">
<button id="delete" type="button">Delete</button>
</form>
<table id="shop">
<caption>Products that are available in the store</caption>
<tr>
<th>Name:</th>
<th id="filter">Price:</th>
<th>Count:</th>
</tr>
</table>
</div>
</div>
解决方案
拆/加货后分拣也能使用是必要的
添加/删除后排序不起作用,因为您show()
在添加/删除元素后调用方法,这将重绘整个 HTML,而不附加任何事件,因此最初附加的事件处理程序将被解除绑定。
您需要在show()
方法中附加事件处理程序来解决此问题。
并且无需在您的方法中返回排序后的数组,原始数组this.products
将被排序。
所以不需要声明sorted
数组并返回它,只需编写this.products.sort()
对数组进行排序的代码即可。
sortProductsByPrice(sortOrder) {
this.products.sort((a, b) => {
return a.price > b.price ? sortOrder : -sortOrder;
});
}
演示:
//Product Creation Class
class Product {
constructor(name, count, price) {
this.name = name;
this.count = count;
this.price = price;
}
}
Product.SORT_ORDER_ASC = 1;
Product.SORT_ORDER_DESC = -1;
// Сlass where products are recorded
class Shop {
constructor() {
this.products = [];
}
//method for adding a product
addProduct(newProduct) {
this.products.push(newProduct);
}
//method for remove product by name
deleteProductByName(productName) {
let i = this.products.length;
while (i--) {
if (productName === this.products[i].name) {
this.products.splice(i, 1);
}
}
}
// get total price by all products
get totalProductsPrice() {
return this.products.map(product => product.price).reduce((p, c) => p + c);
}
//method for sorting the product at its price
sortProductsByPrice(sortOrder) {
this.products.sort((a, b) => {
return a.price > b.price ? sortOrder : -sortOrder;
});
}
// method to draw the table with product property (
// name, count, price)
show() {
const rows = document.querySelectorAll("#shop .data");
for (let i = rows.length - 1; i >= 0; i--) {
const e = rows.item(i);
e.parentNode.removeChild(e);
}
const table = document.getElementById("shop");
const tFoot = table.querySelector('tfoot');
if (tFoot) tFoot.remove();
for (let i = 0; i < this.products.length; i++) {
//create table
table.innerHTML += `<tbody><tr class="data"><td>${this.products[i].name}</td>
<td>${this.products[i].price}</td>
<td>${this.products[i].count}</td></tr></tbody>`;
}
//show total price by all products
table.innerHTML += `<tfoot><tr><td colspan="3" id="total-price">Total price:
${shop.totalProductsPrice}</td></tr></tfoot>`;
}
}
// add new product by click
const formAdd = document.forms[0];
const inputsAdd = formAdd.elements;
const buttAdd = formAdd.elements[3];
buttAdd.addEventListener('click', (e) => {
e.preventDefault();
shop.addProduct(new Product(inputsAdd[0].value, parseInt(inputsAdd[2].value),
parseInt(inputsAdd[1].value)));
shop.show();
}, false);
// delete product by name after click
const formDelete = document.forms[1];
const nameDelete = formDelete.elements[0];
const buttDelete = formDelete.elements[1];
buttDelete.addEventListener('click', (e) => {
e.preventDefault();
shop.deleteProductByName(nameDelete.value);
shop.show();
}, false);
let shop = new Shop();
shop.addProduct(new Product("product", 1, 2000));
shop.addProduct(new Product("product1", 2, 500));
shop.addProduct(new Product("product2", 3, 1000));
shop.show();
const priceFilter = document.getElementById("filter");
//filter products by price
priceFilter.addEventListener("click", (e) => {
shop.sortProductsByPrice(Product.SORT_ORDER_ASC);
shop.show();
}, false);
<div class="Shop">
<div class="add-product">
<h1>Add product</h1>
<form id="addForm">
<label for="name">Name of product</label>
<input type="text" id="name" class="input-product">
<label for="price">Price of product</label>
<input type="text" id="price" class="input-product">
<label for="count">Count of product</label>
<input type="text" id="count" class="input-product">
<button id="add">Add</button>
</form>
</div>
<div class="product-table">
<h2>Products</h2>
<form id="delete-form">
<label for="name-delete">Delete product by name</label>
<input type="text" id="name-delete" class="input-delete">
<button id="delete" type="button">Delete</button>
</form>
<table id="shop">
<caption>Products that are available in the store</caption>
<tr>
<th>Name:</th>
<th id="filter">Price:</th>
<th>Count:</th>
</tr>
</table>
</div>
</div>
推荐阅读
- python - 在 Numpy 数组(Nx2 数组)上查找特定值的最快方法
- javascript - 如何使用 jquery 为每个按钮设置功能?
- python - 如何通过对 (r,c) 数据帧的每个元素执行函数来创建 (r,c,n) 数组?(Python)
- python - 如何在 x 值大小而不是计数之后在 pandas barplot 中排列条形图
- node.js - 如何自动获取每小时的mongodb记录?
- python - 如何按名称选择多个不相邻的列并结合几种切片方法?
- ruby-on-rails - 添加验证以防止 ActiveRecord::Type::Integer 超出范围,限制为 4
- c# - BizTalk 业务流程中的日期时间格式
- google-analytics - 为什么谷歌优化不通过谷歌分析“要求”加载?
- android - 使用 MediaPlayer 在 Xamarin 的主要活动中播放音频不起作用