【问题标题】:Objects synchronised对象同步
【发布时间】:2018-03-30 02:51:12
【问题描述】:

我的 angular4 应用程序中发生了一件非常奇怪的事情,我一生都无法弄清楚。

本质上是我

  1. 将产品和项目的完整列表中的 (@Input) 加载到名为 products 的对象中。
  2. 在名为实体的对象中加载 (@Input),该对象包含具有完整产品列表子集的产品属性,即只有用户保存到实体中的产品。
  3. 加载产品数据 - 我将每个产品从 this.products 推送到 productSelectionData
  4. 然后我运行一个函数,循环遍历 productSelectionData 中的所有项目,并检查实体对象中是否有任何具有名为 selected 的属性的项目,并将 selected 的值更改为 true

此时一切看起来都很好

  1. 然后我运行一个函数来拼接 selectedProducts 和选中属性为 false 的项目。

这就是问题发生的地方。由于某些对我来说并不明显的原因,productSelectionData 对象和 selectedProducts 对象都将带有 selected = false 的项目从数组中拼接出来。

代码如下:

import { Component, Input, OnInit } from '@angular/core';
import { ProposalModel, ProductModel } from './../../../shared/models/';

@Component({
  selector: 'mj-proposal-edit',
  templateUrl: './proposal-edit.component.html',
  styleUrls: ['./proposal-edit.component.scss']
})
export class ProposalEditComponent implements OnInit {

  @Input() entity: ProposalModel;
  @Input() products: ProductModel[];

  productSelectionData: any;
  selectedProducts: any;

  constructor() { }

  ngOnInit() {

    // Load all products and items
    this.loadProductData();
    this.updateProductSelectionData();
    this.filterProductsSelected();

  }

  loadProductData() {
    this.productSelectionData = [];

    this.products.forEach(product => {
      this.productSelectionData.push(
        { productTitle: product.productTitle, items: product.items })
    });
    console.log('Product Selection, after load: ', this.productSelectionData);
    debugger;
  }

  updateProductSelectionData() {
    // Update Product Selection Object with previously selected data

    // 1. Check if there is previously saved data
    if (this.entity.products !== undefined) {
      // 2. Update productSelectionData with values saved in entity object
      this.productSelectionData.forEach(product => {
        if (this.entity.products !== undefined) {
          this.entity.products.forEach(entityProduct => {
            if (product.productTitle === entityProduct.productTitle) {
              if (product.items !== undefined) {
                product.items.forEach(item => {
                  if (entityProduct.items !== undefined) {
                    entityProduct.items.forEach(entityItem => {
                      if (item.code === entityItem.code) {
                        item.selected = true;
                        item.quantity = entityItem.quantity;
                        item.discount = entityItem.discount;
                      }
                    });
                  }
                });
              }
            }
          });
        }
      });
      console.log('Product Selection, after update: ', this.productSelectionData);
      debugger;
    }
  }

  filterProductsSelected() {
    this.selectedProducts = [];
    this.productSelectionData.forEach(product => {
      this.selectedProducts.push(product)
    });
    this.selectedProducts.forEach(selectedProduct => {
      selectedProduct.items.forEach(item => {
        const itemIndex = selectedProduct.items.indexOf(item);
        if (item.selected === false) {
          selectedProduct.items.splice(itemIndex, 1);
        }
        if (item.selected === undefined) {
          selectedProduct.items.splice(itemIndex, 1);
        }
      });
    });
    console.log('Selected Products, after filter: ', this.selectedProducts);
    console.log('Product Selection, after filter: ', this.productSelectionData);
    debugger;
  }

}

【问题讨论】:

    标签: javascript angular typescript


    【解决方案1】:

    在您的 filterProductsSelected 中,您将产品(及其items 数组)推送到您的this.selectedProducts 数组中。

    您最终会在this.selectedProductsthis.productSelectionData 中引用您的产品及其items

    所以,当你在这里拼接时: selectedProduct.items.splice(itemIndex, 1);

    您正在拼接同一个items 数组。

    我克隆了产品对象及其项目数组,它似乎可以工作:

    function filterProductsSelected() {
        selectedProducts = [];
        productSelectionData.forEach(product => {
          // cloning the product :
          var productClone = clone(product);
          // and its items :
          productClone.items = product.items.slice();
          selectedProducts.push(productClone);
        });
        selectedProducts.forEach(selectedProduct => {
          selectedProduct.items.forEach(item => {
            const itemIndex = selectedProduct.items.indexOf(item);
            if (item.selected === false) {
                console.log("not selected");
              selectedProduct.items.splice(itemIndex, 1);
            }
            if (item.selected === undefined) {
                console.log("undefined selected");
    
            selectedProduct.items.splice(itemIndex, 1);
            }
          });
        });
        console.log('Selected Products, after filter: ', selectedProducts);
        console.log('Product Selection, after filter: ', productSelectionData);
        debugger;
      }
    

    克隆功能代码:

    function clone(obj) {
        if (null == obj || "object" != typeof obj) return obj;
        var copy = obj.constructor();
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
        }
        return copy;
    }
    

    【讨论】:

    • 哇,谢谢。我刚刚学到了一些东西,我不知道 .push 从一个对象到另一个对象会创建一个引用,我认为它完全相反。在接下来的几天里,我将查看您的代码。再次感谢您的解释和代码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-12
    • 1970-01-01
    • 1970-01-01
    • 2015-08-29
    • 2012-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多