KnockoutJS 的购物车逻辑(?)问题

2024-03-07

The Goal

制作动态产品列表。

场景

我有一个包含产品的购物应用程序。当我点击add button的产品,我想在侧边栏中显示我添加的产品。

问题总结(您只需阅读此内容)

我的代码中有以下代码ProductsSummary/Index.cshtml(使用 Razor 引擎):

<ul class="summary">
    @if (Session["ProductsSummary"] == null)
    {
        <li class="is-empty">
            <p>Your summary is empty.</p>
        </li>
        <li data-bind="attr: { 'data-product-id': id }">
            <div class="product-summary-actions float-right">
                <button class="btn btn-danger btn-mini remove-item">
                    <i class="icon-remove"></i>
                </button>
            </div>
            <div class="product-summary-quantity">
                <h6 data-bind="text: infoComposition"></h6>
            </div>
            <div class="product-summary-description">
                <p data-bind="text: name"></p>
            </div>
        </li>
    }
    else
    {
        foreach 
          (var product in 
             (List<MyApp.Models.Data.getSpecificProductToShoppingList_Result>)
                Session["ProductsSummary"])
        {
        <!-- ko foreach: products -->
        <li data-product-id="@product.id">
            <div class="product-summary-actions float-right">
                <button class="btn btn-danger btn-mini remove-item">
                    <i class="icon-remove"></i>
                </button>
            </div>
            <div class="product-summary-quantity">
                <h6>
                   @product.quantity 
                   @product.measure@(@product.quantity == 1 ? "" : "s")
                </h6>
            </div>
            <div class="product-summary-description">
                <p>@product.name</p>
            </div>
        </li>
        <!-- /ko -->
        }
    }
</ul>

正如你所看到的,有三个<li>在代码上。第一个是显示一条消息“摘要为空”。如果会话为空(当然,如果添加了任何产品,则会话为空);第二li当我在会话为空时添加一些内容时,作为淘汰赛的模型;最后一项是显示会话中的产品。

我感觉有点"DRY http://en.wikipedia.org/wiki/Don%27t_repeat_yourself"就在这儿。无论会话是否存在,如何重复使用相同的模板?

详细问题

我的代码中有以下代码ProductsSummary/Index.cshtml(使用 Razor 引擎):

<ul class="summary">
    @if (Session["ProductsSummary"] == null)
    {
        <li class="is-empty">
            <p>Your summary is empty.</p>
        </li>
        <li data-bind="attr: { 'data-product-id': id }">
            <div class="product-summary-actions float-right">
                <button class="btn btn-danger btn-mini">
                    <i class="icon-remove"></i>
                </button>
            </div>
            <div class="product-summary-quantity">
                <h6 data-bind="text: infoComposition"></h6>
            </div>
            <div class="product-summary-description">
                <p data-bind="text: name"></p>
            </div>
        </li>
    }
    else
    {
        foreach 
          (var product in 
             (List<MyApp.Models.Data.getSpecificProductToShoppingList_Result>)
                Session["ProductsSummary"])
        {
        <!-- ko foreach: products -->
        <li data-product-id="@product.id">
            <div class="product-summary-actions float-right">
                <button class="btn btn-danger btn-mini remove-item">
                    <i class="icon-remove"></i>
                </button>
            </div>
            <div class="product-summary-quantity">
                <h6>
                   @product.quantity 
                   @product.measure@(@product.quantity == 1 ? "" : "s")
                </h6>
            </div>
            <div class="product-summary-description">
                <p>@product.name</p>
            </div>
        </li>
        <!-- ko -->
        }
    }
</ul>

正如你所看到的,有一个if检查是否ProductsSummary会话存在。如果是,则应用程序会在屏幕上显示我在摘要中添加的产品列表。

案例会议is null,如您所见,应用程序在li with is-empty class.

重点是:我really之后需要“模板”<li class="is-empty">[...]</li>显示添加到摘要中的项目?

我的意思是,我知道当我单击“添加产品”按钮时,无论是否有会话,Knockout 都需要显示一些内容,但我出于类似目的而重复相同的模板。

看这个片段:

<li data-product-id="@product.id">
    <div class="product-summary-actions float-right">
        <button class="btn btn-danger btn-mini remove-item">
            <i class="icon-remove"></i>
        </button>
    </div>
    <div class="product-summary-quantity">
        <h6>
           @product.quantity 
           @product.measure@(@product.quantity == 1 ? "" : "s")
        </h6>
    </div>
    <div class="product-summary-description">
        <p>@product.name</p>
    </div>
</li>

在这种情况下,我在内部使用它foreach因为我必须显示从数据库中获取的项目。

另一方面,如果没有会话,则存在以下片段:

<li data-bind="attr: { 'data-product-id': id }">
    <div class="product-summary-actions float-right">
        <button class="btn btn-danger btn-mini">
            <i class="icon-remove"></i>
        </button>
    </div>
    <div class="product-summary-quantity">
        <h6 data-bind="text: infoComposition"></h6>
    </div>
    <div class="product-summary-description">
        <p data-bind="text: name"></p>
    </div>
</li>

正如您所看到的,这两个片段是相似的 - 一个代表数据库中的数据,另一个代表没有会话时使用 Knockout 的模型 - 我需要一种方法来“模板化”它。

我真正需要什么

  1. 有人进入我的网站/应用程序;
  2. 在我的布局的右侧有一个侧边栏,上面有一条消息:“摘要为空。”;
  3. “哦,多好的产品!我会将其添加到我的摘要中!”,然后用户单击Add按钮,“摘要为空”。消息消失,用户添加的产品以列表中项目的格式显示(与我之前通过的[第一个/第二个片段]相同的模板)。
  4. “好的,我现在转向另一类产品。” — *用户点击“电视”类别* —“天哪!看看这台电视!我现在就添加到我的摘要中!” — *用户单击随机电视的“添加按钮”。* — 列表中已有一个产品,但出现了另一个产品(电视)。
  5. “哦,没关系。我没有钱。我会把这些项目从我的摘要中删除。” — *用户单击摘要上每个产品的“删除按钮”* — 如果没有产品,摘要将显示:“摘要为空”。就像魔法一样,没有任何刷新之类的东西。

(有趣吧?)

KnockoutJS 脚本

$(document).ready(function () {
    function Product(id, name, measure, quantity) {
        this.id = ko.observable(id);
        this.name = ko.observable(name);
        this.measure = ko.computed(function () {
            return quantity > 1 ? measure + "s" : measure;
        }, this);
        this.quantity = ko.observable(quantity);
        this.infoComposition = ko.computed(function () {
            return this.quantity() + " " + this.measure()
        }, this);
    }

    function SummaryViewModel() {
        this.products = ko.observableArray([]);

        this.addToSummary = function (formElement) {
            var $productId = $(formElement).children("[name=productId]").val();

            var match = $(".summary")
                           .find("li[data-product-id=" + $productId + "]").length;

            if (!match) {
                var $productName = 
                        $(formElement).children("[name=productName]").val(),
                    $productMeasure = 
                        $(formElement).children("[name=productMeasure]").val(),
                    $productQuantity = 
                        $(formElement).children("[name=productQuantity]").val();

                this.products.push
                   (new Product
                       ($productId, 
                        $productName, 
                        $productMeasure, 
                        $productQuantity));

                $.ajax({
                    type: "POST",
                    url: "/ProductsSummary/Add",
                    data: 
                       { 
                         productId: $productId, 
                         productQuantity: $productQuantity 
                       }
                });
            }
        }
    };

    var summaryViewModel = new SummaryViewModel();
    ko.applyBindings(summaryViewModel);

    $("body").on("click", ".remove-item", function () {
        summaryViewModel.products.remove(ko.dataFor(this));

        $.ajax({
            type: "POST",
            url: "/ProductsSummary/Remove",
            data: { productId: $(this).closest("li").data("product-id") }
        });
    });
});

最终会发生什么?

我正在做的事情有效和无效。从技术上讲,我的代码可以工作,但我不会重复它。是否可以?

技术细节

服务器端团队是带有 MVC 4 和 Razor 引擎的 C#.NET客户端团队是KnockoutJS 和 jQuery.


对于空购物车消息,您可以执行以下操作:

<li class="is-empty" data-bind="visible: products().length < 1">
    <p>Your summary is empty.</p>
</li>

对于其余的,您应该能够执行此操作(无 MVC 循环):

     <!-- ko foreach: products -->
     <li data-bind="attr: { 'data-product-id': id }">
        <div class="product-summary-actions float-right">
            <button class="btn btn-danger btn-mini remove-item">
                <i class="icon-remove"></i>
            </button>
        </div>
        <div class="product-summary-quantity">
            <h6 data-bind="text: infoComposition"></h6>
        </div>
        <div class="product-summary-description">
            <p data-bind="text: name"></p>
        </div>
    </li>
    <!-- /ko -->

并在客户端填充列表,即使您已将项目保存到会话中。在您看来,将现有数据序列化为 JSON 对象,并将其保存到页面上的 javascript 变量中,该变量可以在文档就绪时读取并推送到可观察的产品中。

var existingItems = @Html.Raw(Json.Encode((List<MyApp.Models.Data.getSpecificProductToShoppingList_Result>)Session["ProductsSummary"]));

$(document).ready(function() {
    // push existingItems into products observable.
});

请注意,我的语法在 JSON 编码上可能不太正确。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

KnockoutJS 的购物车逻辑(?)问题 的相关文章

随机推荐

  • Mysql:检查范围时间冲突[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我有下表 其中存储了教师的课堂例程
  • 使用正则表达式过滤并返回匹配的数字

    在这里 我尝试使用正则表达式从文本中过滤特定的电话号码 电话名称可能有这样的漏洞 4023one345233应被视为40231345233然后应该过滤 这段代码运行良好 没有漏洞 code1 arrwords array 0 gt zero
  • 如何安全地存储 Android KeyStore 密码

    在一个应用程序中 我使用 Android KeyStore 我已经为整个密钥库和每个密码条目设置了一个密码 由于这些密码是字符串 因此它们存储在代码中的字符串成员中 显然 如果我想发布应用程序 这是不安全的 因为潜在的攻击者可以反编译 ap
  • 按降序按组连接值[重复]

    这个问题在这里已经有答案了 我想要一个数据 我的数据 A 看起来像 author id paper id prob 731 24943 1 731 24943 1 731 688974 1 731 964345 8 731 1201905
  • 如何根据 C11 使用二进制前缀?

    我目前正在开始使用微控制器编程C30 A C编译器基于GCC从微芯片为他们PIC24设备 并且我启用了Strict ANSI warnings出于好奇 首先 我不知道在 C11 中 像 这样的注释标记是 错误的 而我应该使用 blah bl
  • 是否可以访问 ViewPager 正在查看的当前 Fragment?

    我有一个应用程序ViewPager和三个Fragments 我想弄清楚如何获得当前Fragment被查看 以便我能够了解其论点 我有一个OnPageChangeListener获取当前页面索引 但是 ViewPager getChildAt
  • Spring Security 条件default-target-url

    我注意到有几个关于这个主题的问题 我浏览了它们 但无法将它们应用到我的特定 Spring 设置中 我想根据用户的角色将登录重定向配置为有条件的 这是我到目前为止所拥有的
  • 如何将所有背景设置为透明以便可以看到主屏幕?

    我想了好几天这个问题 如何将应用程序中的所有背景设置为透明 以便可以看到iOS桌面和图标 有什么方法可以帮助满足需求吗 我仍然没有对图像进行采样的权限 我尝试过一些方法 我把整个iOS系统看成一个大app 当我们在桌面上打开一个应用程序时
  • 将多个协议 Array> 向下转换为 Array

    所以我有两个数组 var arrayOne Array
  • 向 ASP.NET MVC 的 SiteMap 添加自定义属性

    我在 ASP NET MVC 中使用内置的 ASP NET 站点地图 具有以下架构 http schemas microsoft com AspNet SiteMap File 1 0 http schemas microsoft com
  • 如何在 python 中将数据(或单点)添加到现有的 3d 散点图表达图中

    我有一段代码可以绘制与此类似的图 import plotly express as px import plotly graph objects as go df px data tips fig go Figure data go Sca
  • 无法将 Flask 部署到 Azure

    我正在尝试部署python flask to azure但无法打通 我创建了一个 api 服务Azure 这里是url for my api 并且它与python 3 https textclassifier azurewebsites n
  • PHP crypt() 的输出长度是多少? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions PHP的输出长度是多少crypt m
  • 如何在 SQL Server 中向用户定义的表类型添加索引或主键?

    我有一个用户定义的类型 我想向其中添加主键或索引 IF NOT EXISTS SELECT FROM sys types st JOIN sys schemas ss ON st schema id ss schema id WHERE s
  • 如何在uwp中为特定sdk定义条件编译器符号

    我正在 Visual Studio 2015 中编写一个 UWP 应用程序 最小 sdk 是 10240 最大是 14393 我想编写 sdk 特定代码 所以我想定义一个条件编译符号 我可以简单地在构建选项卡下的项目属性窗口中定义它 但是我
  • 推荐的 VBA IDE [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有推荐的 IDE 用于开发 Excel VBA 宏 提供合理的错误报告和代码完成 目前 我使用的是
  • 插入到android sqlite数据库中的特定行

    我正在寻找一种方法将新条目插入到 android 中的 sqlite 数据库中的特定行中 基本思想是数据库存储如下条目 id day time 1 Monday 09 00 2 Monday 11 00 3 Tuesday 10 00 ID
  • Amazon CloudSearch 从 DynamoDB 创建 Null ID

    我正在尝试开始使用 Amazon CloudSearch 我的数据位于我想要搜索的 DynamoDB 表中 我能够设置云搜索域 它从表中提取字段并让我设置它们 等等 但是 我上传数据时遇到了一些问题 我告诉它要从中提取 DynamoDB 表
  • 结果值在 '? :' 表达式的类型 '()' 和 'Bool' 不匹配[重复]

    这个问题在这里已经有答案了 我有一个双精度数组和一个按钮 按下该按钮会清空数组 我希望仅当数组的计数大于零时才启用该按钮 代码如下 var numbers Double At some point I add some numbers he
  • KnockoutJS 的购物车逻辑(?)问题

    The Goal 制作动态产品列表 场景 我有一个包含产品的购物应用程序 当我点击add button的产品 我想在侧边栏中显示我添加的产品 问题总结 您只需阅读此内容 我的代码中有以下代码ProductsSummary Index csh