警告:这是一本长篇小说,因为有很多与该问题有关的信息,所以请做好准备,并感谢您抽出宝贵的时间来解决此问题!
我正在为一个客户端编写一个非常大的WebApp,并为此使用jQuery构建了许多交互式应用程序,但是我开发的一个应用程序使我感到奇怪:是否有一种标准的方法可以执行此操作,或者更好的方法吗?
这是我来到你们这里的目的,以了解是否应该采取某种特定的方法,因为我一直在寻求构建最佳的应用程序。
我必须完成的任务
我正在构建的应用要求用户能够构建产品的发票。该发票可以通过搜索框添加任何数量的产品。每个产品都从数据库中提取并存储在该搜索框中,每个产品可以多次添加。
用户添加产品的方式是在搜索框中输入产品名称,然后按添加产品按钮。这会将处理后的模板添加到产品列表中。很简单吧?
问题
我遇到的一个大问题是,发票不仅可以包含产品列表,而且每个产品都包含不同的可定制详细信息。这意味着每个产品上都有许多自己的字段,用户可以编辑这些字段,从而修改了许多内容。例如,一种类型的产品具有数量,该数量需要乘以该产品的成本价格才能返回总价格。另一个产品的长度,需要乘以宽度,然后再乘以该产品的成本价格即可返回总价。
您可以想象,有许多不同类型的产品和许多不同的字段和有很多不同的计算方式,在创建结束时,需要解析为一个PHP页面,同时保持完全可修改性,用户可以在同一发票页面上添加/删除/编辑产品,而无需四处浏览。
对我来说,这是一场噩梦,因为我需要一种方法来保持这种状态整洁,并使一堆不同的输入/ jQuery对象不会以一种或另一种方式相互冲突。我还必须与新创建的产品区别加载,因为有些产品会从数据库中获取信息
我构建的解决方案
因此,当产品位于列表的前面时,该产品包含多个字段,多个详细信息和一个删除按钮。我要做的第一件事是为每种不同类型的产品制作带有可替换标记的模板。这很容易,而且工作得非常好,当一个产品排在该列表的前面时,会向与该产品相关的每个元素添加一个 rel 属性(我称之为“hook”),以便可以添加仅修改具有该特定挂钩的元素的处理程序。
对于输入,我使用了<input name="Products[%HOOK%][%PRODUCTDATAKEY%]" value="%PRODUCTDATAVALUE%" />
形式的输入数组。出现我的主要问题的地方是,我必须将已经保存在数据库中的已加载产品与刚刚添加的新产品区分开。我这样做的方法是在所有输入名称数组之前添加[Loaded],这样我的PHP脚本将能够单独处理[Loaded]数组。
我担心什么?
我最大的担心是,从标记到代码,一切最终看起来如何困惑。 将钩到各处,极长的输入名称,几千行代码,以及需要替换的不同密钥和 token 的头疼,。它工作得非常好,当我将其视为开发人员时,感觉非常糟糕。以这个“添加的产品” 为例:<div class="item product special-order" rel="7" style="">
<input type="hidden" name="products[7][id]" value="17">
<input type="hidden" name="products[7][item_id]" value="">
<input type="hidden" name="products[7][type]" value="Special Order Flooring">
<input type="hidden" name="retail_price" class="invoice-base-cost" value="18.49">
<h4>Carpet Brand<a name="action" rel="7" class="btn btn-mini btn-danger remove-product initialized" style=""><i class="icon-remove"></i> Remove</a>
</h4>
<div class="item-details">
<div class="detail-column">
<div class="detail">
<span class="detail-label detail-label-medium"> Type:</span>Carpet
</div>
<div class="detail">
<span class="detail-label detail-label-medium">Range:</span> Carpet Brand
</div>
<div class="detail">
<span class="detail-label detail-label-medium">
Colour:</span><input required="" class="detail-input-large left-align" value="" type="text" name="products[7][colour]">
</div>
<div class="detail">
<span class="detail-label detail-label-medium">
Length:</span><input type="text" name="products[7][length]" rel="7" class="length-field initialized" placeholder="Enter the length..." value="1.000"><span class="detail-unit">m</span>
</div>
</div>
<div class="detail-column">
<div class="detail">
<span class="detail-label detail-label-large">Manufacturer:</span>
<select class="detail-input-large" required="" name="products[7][manufacturer_id]">
<option value="14">Manufacturer 1</option>
<option value="16">Manufacturer 2</option>
</select>
</div>
<div class="detail">
<span class="detail-label detail-label-large">Width supplied:</span><input type="text" name="products[7][width]" class="width-field" value="5.000"><span class="detail-unit">m</span>
</div>
<div class="detail">
<span class="detail-label detail-label-large">Retail price per/m:</span> £18.49
</div>
<div class="detail">
<span class="detail-label detail-label-large">Room:</span><input class="detail-input-large left-align" type="text" name="products[7][room]" value="" required="required">
</div>
</div>
<div class="item-cost">
<h5>Item cost</h5>
£<span class="invoice-cost" rel="7">92.45</span>
</div>
</div>
</div>
那不是过度杀了吗?难道我没有将它们映射到JSON对象以使其更干净吗?还是这是正确的方法?
该产品也有大约 5个不同的事件也绑定(bind)了,这很困惑,因为如果更改长度字段,,则必须通过宽度和基础价格重新计算价格,与宽度只是向后,而这都是由查找具有相同rel(钩)的字段完成的...对我来说,这看起来像是一团糟。最好就如何处理这一问题获得专家意见。
最佳答案
我对前两个答案表示赞同:使用旨在处理此问题的框架。
但是,在进行此操作之前,这是朝着模块化代码迈出的第一步:根据您的描述,您似乎已经有了.special-order
项列表,并且每个项都有其自己的生命。
尝试在您的标记和代码中体现这一点:
1-标记:使用有意义的类名称来标识将扮演积极角色的项目(您似乎已经拥有:.special-order
,.length-field
,.remove-button
...)。确保有一个单个节点来包装整个html“bundle”(在您的情况下:.special-order
似乎扮演了这个角色)。
2-事件挂钩:使用这些类名称来绑定(bind)您的挂钩:
$('.remove-button').click(function(){ ... });
$('.length-field').change(function(){ ... });
3-如果项目列表是动态的(例如,您可以通过javascript添加/删除项目,而无需重新加载整个页面),请使用event delegation绑定(bind)事件:
$('.special-order-list').on('click', '.remove-button', function(){ ... });
$('.special-order-list').on('change', '.length-field', function(){ ... });
4-在处理程序内部,遵循标记中表示的模块化。如果两个节点是相同
.special-order
节点的子节点,则它们是相关的。这样,您可以表示节点之间的关系,该关系不依赖于“rel”字段的显式值: $('.special-order-list').on('change', '.length-field', function(){
var $masterNode = $(this).closest('.special-order');
var basePrice = $masterNode.find('.base-price').val();
var length = $(this).val();
$masterNode.find('.total-price').val( basePrice * length );
});
5-显然,在适当的地方使用函数:
function recomputePrice($masterNode){
var basePrice = $masterNode.find('.base-price').val();
var length = $masterNode.find('.length-field').val();
$masterNode.find('.total-price').val( basePrice * length );
});
$('.special-order-list').on('change', '.length-field, .base-price', function(){
var $masterNode = $(this).closest('.special-order');
recomputePrice( $masterNode );
});
将页面组织成模块和子模块(有些将它们称为组件或小部件……)被认为是页面布局的“最佳实践”。在SmaCSS中提到了is,它是多个css / js框架的基础,例如Bootstrap或许多其他框架。
关于php - 用JS/jQuery编写此代码的最佳方法是什么? (具有多个字段的多个单个对象),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18401456/