4

警告:这是一篇很长的文章,因为有很多与问题相关的信息,所以请做好准备,如果你愿意,感谢您抽出宝贵的时间阅读!

我正在为客户编写一个非常大的 WebApp,并且已经使用 jQuery 为此构建了许多交互式应用程序,但是我开发的一个让我想知道:有没有一种标准的方法来做到这一点,或者可能只是一个更好的方法

这就是我来找你们的地方,以了解是否有某种方法可以做到这一点,因为我一直在寻找构建最佳应用程序。

我必须完成的任务

我正在构建的应用程序要求用户能够构建产品发票。该发票可以通过搜索框添加任意数量的产品。每个产品都从数据库中提取并存储在该搜索框中,并且每个产品都可以添加多次。

用户添加产品的方式是在搜索框中输入产品名称,然后按“添加产品”按钮。这会将已处理的模板添加到产品列表中。很简单吧?

问题

我遇到的一个大问题是,不仅发票能够包含产品列表,而且这些产品中的每一个都包含不同的可定制细节。这意味着每个产品上都有许多自己的字段,用户可以编辑这些字段,从而修改了许多内容。例如,一种产品有数量,需要乘以该产品的成本价格才能返回总价格。另一种产品有一个length,需要乘以width,然后需要乘以该产品的成本价格以返回总价。

可以想象,有许多不同类型的产品具有许多不同的字段,需要进行许多不同的计算,在创建结束时,需要将其解析为 PHP 页面,同时保持用户可以添加/的完全可修改性在同一发票页面上删除/编辑产品而无需跳转。

对我来说,这是一场噩梦,因为我需要有一种方法来保持这种清洁,并且有一堆不同的输入/jQuery 对象不会以某种方式相互碰撞。我还必须区分加载的产品和新创建的产品,因为有些产品会从数据库中获取信息。

我构建的解决方案

因此,当产品被添加到列表中时,该产品包含许多字段、许多详细信息和一个删除按钮。我做的第一件事是为每种不同类型的产品制作带有可替换标记的模板。这很简单,而且工作得非常好,当一个产品被添加到列表中时,对于与该产品相关的每个元素,我添加了一个rel属性(我称之为“钩子”),以便我可以添加处理程序仅使用该特定钩子修改元素

对于输入,我使用了输入数组,格式为<input name="Products[%HOOK%][%PRODUCTDATAKEY%]" value="%PRODUCTDATAVALUE%" />. 我的主要问题出现在哪里,我必须将已加载的已保存在数据库中的产品与刚刚添加的新添加产品区分开来。我这样做的方法是在所有输入名称数组之前添加 [Loaded],以便我的 PHP 脚本能够单独处理 [Loaded] 数组。

我有什么顾虑?

我最担心的是,从标记到代码,一切最终看起来有多混乱。到处乱飞的钩子,极长的输入名称几千行代码以及要替换的不同键和令牌令人头疼。它工作得很好,当我作为开发人员看待它时感觉很糟糕。以这个“附加产品”为例:

<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 个不同的事件绑定,这很混乱,因为如果更改了长度字段,则必须根据宽度和基础价格重新计算价格,并且宽度正好向后,这一切都是通过寻找具有相同 rel (钩子)的字段来完成的......对我来说这看起来很乱。就应该如何处理这个问题获得专家意见会很棒。

4

3 回答 3

3

我支持前两个答案:使用旨在处理此问题的框架。

然而,在去那里之前,这是模块化代码的第一步:根据您的描述,您似乎有一个.special-order项目列表,每个项目都有自己的生命。

尝试在您的标记和代码中反映这一点:

1- 标记:使用有意义的类名来识别将发挥积极作用的项目(您似乎已经拥有 : .special-order, .length-field, .remove-button...)。确保有一个单独的节点来包装你的整个 html“捆绑包”(在你的情况下:.special-order似乎扮演这个角色)。

2-事件钩子:使用这些类名来绑定你的钩子:

$('.remove-button').click(function(){  ...  });
$('.length-field').change(function(){ ... });

3- 如果您的项目列表是动态的(例如,您可以通过 javascript 添加/删除项目而无需重新加载整个页面),请使用事件委托来绑定您的事件:

$('.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中提到了它,它是几个 css/js 框架的基础,例如Bootstrap或许多其他框架。

于 2013-09-02T08:44:15.140 回答
3

正如 spez86 所建议的那样;您应该使用框架来生成您的 HTML 以及将事件绑定到每个 HTML 部分中存在的元素。我会建议你看一下backbonejshandlebarsjs。当您结合使用这两个时,您需要付出最小的努力来实现您的目标。
您可以参考以下URL以了解更多关于它们的使用情况。
我会建议您首先在 UI 上工作,即为您不同类型的产品创建单独的模板,然后在您的添加产品按钮上单击尝试将主干视图附加到您的产品列表容器。
一旦您能够成功地将 HTML 添加到页面上,您就可以继续将事件绑定到产品模板中存在的子元素。这可以在 Backbone.View 类的events函数中完成。此处注册的事件处理程序将仅附加到此视图中存在的元素,而不附加到页面 DOM 中具有相同 CSS 类的任何其他元素。因此,您将摆脱[rel]机制以及长输入名称。希望这会对您有所帮助。

于 2013-08-27T13:42:07.287 回答
2

老实说,随着您谈论的数据量和可以修改的方式的数量,您应该研究一个更强大的框架,并且旨在使数据绑定更容易。那里有很多,但我个人最喜欢的是 AngularJS。

http://angularjs.org/

开始研究这一点,因为它可以为您节省大量开发应用程序的时间,然后当然可以在以后维护它。

于 2013-08-23T15:18:45.443 回答