我不太擅长淘汰赛,所以我可能错过了一些东西。
我的用例:
我有一个简单的视图模型。我的页面看起来像这样
<body>
<hr />
<div>
<label for="">
Basic :</label>
<input type="text" name="" data-bind="value: basic" id="txtBasic" />
</div>
<div>
<label for="">
HRA :</label>
<input type="text" name="" data-bind="value: hra" id="txtHra" />
</div>
<div>
<div style="background-color:silver;">
<hr />
<label for="">
<input type="button" data-bind="click : generateModelValue" value="Generate Runtime Property" />
<input type="button" data-bind="click : tryRebind" value="Try Rebinding with clean node" />
<br>
DA :</label>
<input type="text" name="" id="txtDa" data-bind="value: $data.da"><br><br></div>
</div>
<hr />
<div>
<label for="">
Tax :</label>
<input type="range" name="" id="rangeTax" min="0" max="30" value="0" data-bind="value: tax" />
<span id="spanTax">[Tax%]</span>
</div>
<div>
<input type="button" value="Calculate" id="btnCalculate" data-bind="click: computeSalary" />
</div>
<div>
<div id="divResult" data-bind="text: salary">
[Salary]</div>
</div>
</div>
<script>
myViewModel={
basic: ko.observable(1000),
hra: ko.observable(10),
tax: ko.observable(10),
salary: ko.observable('Yet to be calculated'),
computeSalary: function () {
this.salary(this.basic()+this.da()+this.hra());
},
generateModelValue: function () {
debugger;
this.da=ko.observable("123");
},
tryRebind: function () {
debugger;
alert("Why do i have to call this to update the view model");
ko.cleanNode($('body')[0]);
ko.applyBindings(myViewModel,$('body')[0]);
}
};
ko.applyBindings(myViewModel,$('body')[0]);
</script>
</body>
我想在运行时添加一个属性(在本例中为“da”)。所以为了使示例简单易读,我将在我的模型上调用“ generateModelValue ”函数,这将添加“ myViewModel ”上的“ da ”属性,其示例值为“123”。
这成功创建了一个新的可观察属性(我使用console.log检查)。 但不更新用户界面。
所以在点击之后我在我的视图模型上调用了另一个函数,它将尝试执行 ko.cleanNode($('body')[0]),然后按 ko .applyBindings(myViewModel,$('body')[0]); 然后更新UI。
我的问题:
我是否必须调用干净节点,或者在更新视图模型后有更好的方法来更新UI?
我怀疑:
"<input type="text" name="" id="txtDa" data-bind="value: $data.da">"
在我的HTML中(因此当我使用viewModel中不可用的属性调用applyBinding时,不会抛出未定义的错误) 访问过的帖子:
Adding properties to the view model created by using the Knockout JS mapping plugin
(我不太确定我理解这篇文章。如果推荐,我会再次讨论它,因为我也使用映射插件将普通的json响应从AJAX调用转换为可观察的视图模型但是我的实现有点不同)
Live Plunker: http://plnkr.co/edit/4EwSdKihVak1dGhuobbi?p=preview
<小时/> 已编辑:
因为当我打电话给ko.applybinding时,我的viewModel总是小于我的HTML标记所需的数据绑定属性,因为会抛出未定义的错误(我使用$ data)避免这个错误。)
因此,将在ko.applyBinding(html-element)中传递的最终html视图将是构成屏幕的几个较小的html片段的UNION。
并且在调用apply绑定时无法收集所有视图模型属性,因为视图模型的复杂性会随着用户交互(Ajax调用)而增加
我希望它清楚。如果不是,我正在创造一个同样的傻瓜。会很快更新。
已更新
新的plunkr
http://plnkr.co/edit/8PNHk25jl2xig0GLyqQq?p=preview
在上面的plunkr中带
的部分<div data-bind="visible: $data.da">
You will see this section only if the da property is available on the view model
</div>
在应用绑定时,将存在于DOM中,但“da”的值不会。 并且在一些用户交互之后,视图模型将被更新,因为该对象将通过ajax调用接收新属性(例如,在plunkr之上的da)。因此将显示da部分。
答案 0 :(得分:1)
我认为你误解了淘汰赛应该起作用的方式。存在诸如动态列表等的情况,其中并非所有可观察的都可立即可用。但是,您的observable只是模型上的属性。应与basic
和hra
一起创建此可观察对象。延迟它的创造没有任何好处。
将您的代码更改为:
myViewModel = {
basic: ko.observable(1000),
hra: ko.observable(10),
da: ko.observable(null),
如果要表示在函数generateModeValue
之前尚未设置该值,则让null
表示此值,或者创建该函数可以设置的另一个布尔值observable。例如:
myViewModel = {
basic: ko.observable(1000),
hra: ko.observable(10),
da: ko.observable(null),
daIsSet: ko.observable(false),
...
generateModelValue: function () {
debugger;
this.da("123");
this.daIsSet(true);
},
...
同样,可以动态添加observable(使用数组或其他方法),但这种情况不需要这种功能。希望能为你清除一些概念。
答案 1 :(得分:1)
在运行时添加属性将要求您调用apply bindings。
但是,如果您愿意参与初始设计,答案很简单。
我假设你的工资组件都有一个共同的模型,可以让你得出它们如何添加到薪水计算中。没有细节,我称之为薪水成分。
function salaryComponent(n,v,t){
this.Name = ko.observable(n);
this.Value = ko.observable(v);
this.Type = ko.observable(t);
}
如果您需要按类型自定义显示,我会在工资组件中添加一个类型描述符,然后使用
<div data-bind="foreach: salaryComponents">
<!-- ko if: type() == 1 -->
<data-bind="template: {name:'Da-template',data:$data}
<!-- /ko -->
</div>
在数组中为每个工资组件类型应用模板。这将允许您构建html的snipets来表示每个工资组件。
因此,更改模型以使用可观察数组来处理动态模型添加如下:
myViewModel={
basic: ko.observable(1000),
hra: ko.observable(10),
tax: ko.observable(10),
salary: ko.observable('Yet to be calculated'),
//dynamic salary components
salaryComponents: ko.observableArray(),
computedSalary = ko.computed(function(){
var base = this.basic()+this.hra();
ko.utils.arrayForEach(salaryComponents(), function(item) {
base+=item.Value()
});
return base;
}
generateModelValue: function () {
salaryComponents.push(new salaryComponent('Da',123,1));
},
};
将此设计用于您的模型允许按工资类型的多个模板创建复杂的UI显示,并允许您向视图模型添加组件,而不需要再次调用应用绑定。
哦,最后一件事,没有理由不得不调用计算来确定工资。改为使用计算值:
computedSalary = ko.computed(function(){
var base = this.basic()+this.hra();
ko.utils.arrayForEach(salaryComponents(), function(item) {
base+=item.Value()
});
return base;
}
同样,根据最初发布的内容,并不完全确定这是您正在寻找的内容。