1

我是 Knockout 的新手,我正在构建一个简单的 POC,用于使用 Knockout 构建 SPA(单页应用程序)。

我想要做的是在应用程序加载时显示“业务单位”,并在选择业务单位时显示该业务单位下的所有“前端单位”,在选择前端单位时,在下显示所有“销售部门”那个前端单元。

所有这一切都将发生在使用相同视图的单个页面中,并且视图模型将根据选定的业务单元或前端单元绑定模型。

我面临的问题是,我有 5 个业务单元在准备好文档时首先正确绑定,但是在选择业务单元时,前端单元每个重复 5 次。在这种情况下,我有 2 个前端单元,每个单元显示 5 次。前端单元的选择也有同样的问题。

您可以在以下 jsFiddle 示例中看到此问题 - jsFiddle Link

如果您无法访问 jsfiddle 链接,请告诉我。在这个示例中,我使用了数组,但实际上我将通过对 oData 服务的异步调用来获取数据。

这是视图 HTML:

<div id="divbu">
    <h4 data-bind="text: Heading"></h4>
    <ul data-role="listview" data-inset="true" data-bind="foreach: Collection">
        <li data-role="list-divider" data-bind="text: EntityName"></li>
                <li>
                    <a href="#" data-bind="click: $root.fnNextLevel">
                        <table border="0">
                            <tr>
                                <td>
                                    <label style="font-size: 12px;">Bus. Plan: </label>
                                </td>
                                <td>
                                    <label style="font-size: 12px;" data-bind="text: BusinessPlan"></label>
                                </td>
                                <td>
                                    <label style="font-size: 12px;">Forecast: </label>
                                </td>
                                <td>
                                    <label style="font-size: 12px;" data-bind="text: Forecast"></label>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <label style="font-size: 12px;">Gross Sales: </label>
                                </td>
                                <td colspan="3">
                                    <label style="font-size: 12px;" data-bind="text: GrossSales"></label>
                                </td>
                            </tr>
                        </table>
                    </a>
                </li>
            </ul>
</div>

这是模型和视图模型:

function CommonModel(model, viewType) {
 var self = this;
 if (viewType == 'BU') {
     self.EntityName = model[0];
     self.BusinessUnit = model[0];
     self.BusinessPlan = model[1];
     self.Forecast = model[2];
     self.GrossSales = model[3];
 } else if (viewType == 'FEU') {
     self.EntityName = model[1];
     self.BusinessUnit = model[0];
     self.FrontEndUnit = model[1];
     self.BusinessPlan = model[2];
     self.Forecast = model[3];
     self.GrossSales = model[4];
 } else if (viewType == 'SS') {
     self.EntityName = model[2];
     self.BusinessPlan = model[3];
     self.Forecast = model[4];
     self.GrossSales = model[5];
 }

}

function ShipmentReportsViewModel(results, viewType) {

 var self = this;
 self.Collection = ko.observableArray([]);

 for (var i = 0; i < results.length; i++) {
     self.Collection.push(new CommonModel(results[i], viewType));
 }
 if (viewType == 'BU') {
     self.Heading = "Business Units";
     self.fnNextLevel = function (businessUnit) {
         FetchFrontEndUnits(businessUnit);
     };
     self.Home = function () {
         FetchBusinessUnits();
     };

 } else if (viewType == 'FEU') {

     self.Heading = results[0][0];
     self.fnNextLevel = function (frontEndUnit) {
         FetchSalesSegments(frontEndUnit);
     };
     self.Home = function () {
         FetchBusinessUnits();
     };
 } else if (viewType == 'SS') {
     self.fnNextLevel = function () {
         alert('No activity zone');
     };
     self.Heading = results[0][0] + ' - ' + results[0][1];
     self.Home = function () {
         FetchBusinessUnits();
     };
 }

}

您可以在 jsFiddle 链接中看到完整的代码。

我也尝试过使用多个视图和多个视图模型,我通过提供元素 ID 来应用绑定。在这种情况下,来自业务部门 -> 销售部门的一个流程很好,但是当我单击主页或后退按钮并再次绑定到该元素时,我面临同样的问题。(在 jsFiddle 示例中没有完成主页和后退按钮功能)。

如果需要更多详细信息,请告诉我。我确实查看了堆栈溢出中的许多其他链接,但没有解决这个特定问题。

任何帮助都深表感谢。提前致谢。

4

2 回答 2

3

这里的问题是您两次调用您的 ko.applybindings 并且有一个 foreach 绑定在 5 个项目内迭代,因此数据重复了五次。

您不应在同一模型上多次调用 ko.applybindings。即使已参数化,您的模型也始终相同。

我在这里遇到了同样的问题:来自 ObservableArray 的数据在我的表中显示了两次

您在 viewModel 中拥有业务逻辑这一事实是可以讨论的,这使得解决这个问题变得不容易。

制作3个类,将它们放在一个没有逻辑的通用模型中。然后,一旦您应用了 ko.applyBindings 一次,您只需像这样修改数组:

viewModel.myArray(newValues)

这是修改后的代码的小提琴:http: //jsfiddle.net/MaurizioPiccini/5B9Fd/17/ 它并不能完全满足您的需要,但是如果通过将 Collection 对象范围移动到模型之外来删除多个绑定。如您所见,问题在于您在同一模型上两次调用 ko.applybindings 。

于 2013-06-10T09:07:27.137 回答
0

最后,我得到了这个工作。感谢@MaurizioIndenmark。

虽然我已经删除了对 ko.applybindings 的多次调用,但我仍然多次调用视图模型。这导致了这个问题。

现在,我有了更清晰的视图模型,并且对不同的操作有不同的函数调用,并修改了这些函数(事件)中需要修改的所有数据。现在,一切都按预期工作。

这就是视图模型现在的样子 -

function ShipmentReportsViewModel(results) {
var self = this;
self.Heading = ko.observable();
self.BusinessUnits = ko.observableArray();
self.FrontEndUnits = ko.observableArray();
self.SalesSegments = ko.observableArray();

self.Home = function () {
    var bu = FetchBusinessUnits();
    self.Heading("Business Units");
    self.BusinessUnits(bu);
    self.FrontEndUnits(null);
    self.SalesSegments(null);
};
self.fnFeu = function (businessUnit) {
    var feu = FetchFrontEndUnits(businessUnit);
    self.Heading(feu[0].BusinessUnit);
    self.FrontEndUnits(feu);
    self.BusinessUnits(null);
    self.SalesSegments(null);
};
self.fnSalesSeg = function (frontEndUnit) {
    var ss = FetchSalesSegments(frontEndUnit);
    self.Heading(ss[0].BusinessUnit + ' - ' + ss[0].FrontEndUnit);
    self.SalesSegments(ss);
    self.BusinessUnits(null);
    self.FrontEndUnits(null);
};
self.Home();
}

要查看整个工作解决方案,请参考这个jsFiddle

感谢您在完成这项工作时提出的所有宝贵建议。

于 2013-06-24T08:20:52.730 回答