首页 > 解决方案 > 为什么按价格排序不起作用?

问题描述

在该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>

标签: javascriptarrayssortingdomecmascript-6

解决方案


拆/加货后分拣也能使用是必要的

添加/删除后排序不起作用,因为您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>


推荐阅读