【发布时间】:2023-03-25 03:28:01
【问题描述】:
目标
制作动态产品列表。
情景
我有一个包含产品的购物应用程序。当我点击某个产品的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" 就在这里。无论会话是否存在,如何重复使用相同的模板?
详细问题
我的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 会话是否存在。如果是,则应用程序会在屏幕上显示我在摘要中添加的产品列表。
如果会话为空,如您所见,应用程序在li 和is-empty 类中显示消息。
重点是:我真的需要<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 一起工作的模型——我需要一种“模板化”它的方法。
我真正需要的东西
- 有人进入我的网站/应用程序;
- 在我的布局右侧有一个带有消息的侧边栏:“摘要为空。”;
- “哦,多好的产品!我会把它添加到我的摘要中!”,然后用户点击
Add按钮,“摘要为空”。消息消失,用户添加的产品以列表中项目的格式出现(与我在 [第一个/第二个片段] 之前传递的相同模板)。- “好的,我现在就去另一类产品。” — *用户点击“电视”类别* —“哦,我的上帝!看看这台电视!我现在将添加到我的摘要中!” — *用户点击随机电视的“添加按钮”。* — 列表中已有产品,但出现了另一个(电视)。
- “哦,没关系。我没有钱。我将从我的摘要中删除这些项目。” — *用户单击摘要上每个产品的“删除按钮”* — 如果没有产品,摘要将显示:“摘要为空。”就像魔术一样,没有任何刷新或类似的东西。
(好笑吧?)
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") }
});
});
});
最终会发生什么?
我正在做的工作和不工作。从技术上讲,我的代码有效,但我不会重复它。有可能吗?
技术细节
服务器端团队使用 C#.NET 和 MVC 4 和 Razor 引擎,客户端团队使用 KnockoutJS 和 jQuery。
【问题讨论】:
-
你能不能试试knockoutjs模板绑定,把你重复的内容放在一个text/html脚本块里...knockoutjs.com/documentation/template-binding.html
-
如果没有别的我喜欢阅读你的问题的上下文
标签: c# javascript asp.net-mvc-4 razor knockout.js