簡體   English   中英

如何在剔除中將屬性添加到可觀察數組中的對象並觸發通知?

[英]How do I add an attribute to an object within an observable array in knockout and trigger a notification?

使用Knockout.js,我的視圖模型中有了一個可觀察的數組。

 function MyViewModel() { var self = this; this.getMoreInfo = function(thing){ var updatedSport = jQuery.extend(true, {}, thing); updatedThing.expanded = true; self.aThing.theThings.replace(thing,updatedThing); }); } this.aThing = { theThings : ko.observableArray([{ id:1, expanded:false, anotherAttribute "someValue" }]) } } 

然后,我有一些html會根據稱為“ expanded”的屬性的值而變化。 它具有一個可單擊的圖標,該圖標應將expand的值從false切換為true(有效更新圖標)

 <div data-bind="foreach: aThing.theThings"> <div class="row"> <div class="col-md-12"> <!-- ko ifnot: $data.expanded --> <i class="expander fa fa-plus-circle" data-bind="click: $parent.getMoreInfo"></i> <!-- /ko --> <!-- ko if: $data.expanded --> <span data-bind="text: $data.expanded"/> <i class="expander fa fa-minus-circle" data-bind="click: $parent.getLessInfo"></i> <!-- /ko --> <span data-bind="text: id"></span> (<span data-bind="text: name"></span>) </div> </div> </div> 

查看我在getMoreInfo()函數中編寫的怪獸,以獲取要更新的html。 我在淘汰賽中使用了observableArrays的replace()函數,這將強制向所有訂閱的對象發出通知。 僅當兩個參數不是同一對象時,replace()才起作用。 因此,我使用jQuery深度克隆來復制對象並更新屬性,然后將其反映到標記上。 我的問題是...有沒有更簡單的方法來實現這一目標?

為了這個問題,我在某種程度上簡化了我的代碼片段。 在用戶對應用執行特定操作之前,“擴展”屬性實際上並不存在。 它是動態添加的,本身不是可觀察的屬性。 我嘗試單獨在此屬性上校准ko.observable(),但是它並不能防止需要在observable數組上調用replace()來刷新UI。

淘汰賽最適合一種架構,在該架構中,具有動態屬性和事件處理程序的模型視圖模型支持。

通過構造視圖模型Thing ,可以大大提高代碼的質量和可讀性。 這是一個例子。 注意模板(=視圖)變得更加清晰。

 function Thing(id, expanded, name) { // Props that don't change are mapped // to the instance this.id = id; this.name = name; // You can define default props in your constructor // as well this.anotherAttribute = "someValue"; // Props that will change are made observable this.expanded = ko.observable(expanded); // Props that rely on another property are made // computed this.iconClass = ko.pureComputed(function() { return this.expanded() ? "fa-minus-circle" : "fa-plus-circle"; }, this); }; // This is our click handler Thing.prototype.toggleExpanded = function() { this.expanded(!this.expanded()); }; // This makes it easy to construct VMs from an array of data Thing.fromData = function(opts) { return new Thing(opts.id, opts.expanded, "Some name"); } function MyViewModel() { this.things = ko.observableArray( [{ id: 1, expanded: false, anotherAttribute: "someValue" }].map(Thing.fromData) ); }; MyViewModel.prototype.addThing = function(opts) { this.things.push(Thing.fromData(opts)); } MyViewModel.prototype.removeThing = function(opts) { var toRemove = this.things().find(function(thing) { return thing.id === opts.id; }); if (toRemove) this.things.remove(toRemove); } var app = new MyViewModel(); ko.applyBindings(app); // Add stuff later: setTimeout(function() { app.addThing({ id: 2, expanded: true }); app.addThing({ id: 3, expanded: false }); }, 2000); setTimeout(function() { app.removeThing({ id: 2, expanded: false }); }, 4000); 
 .fa { width: 15px; height: 15px; display: inline-block; border-radius: 50%; background: green; } .fa-minus-circle::after { content: "-" } .fa-plus-circle::after { content: "+" } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <div data-bind="foreach: things"> <div class="row"> <div class="col-md-12"> <i data-bind="click: toggleExpanded, css: iconClass" class="expander fa"></i> <span data-bind="text: id"></span> ( <span data-bind="text: name"></span>) </div> </div> </div> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM