视图代码:
<ul data-bind="foreach: BackColorOptions">
<li data-bind="css: { selected: Selected }">
<label>
<input type="radio" name="BackColorOption"
data-bind="value: Color, checked: $root.BackColor" />
</label>
</li>
</ul>
@{
var jsonModel = new System.Web.Script.Serialization.
JavaScriptSerializer().Serialize(Model);
}
<input type="hidden" id="JsonModel" value='@jsonModel' />
视图模型代码:
var initialData = $.parseJSON($('#JsonModel').val());
function BackColorOption(data, parent) {
var self = this;
self.parent = parent;
self.Text = ko.observable(data.Text);
self.Color = ko.computed(function () {
return '#' + self.Text().toLowerCase();
});
self.Selected = ko.computed(function () {
var backColor = self.parent.BackColor();
if (backColor) {
return backColor.toLowerCase() == self.Color;
}
return false;
});
}
function TestViewModel() {
var self = this;
self.BackColor = ko.observable(initialData.BackColor);
var mappedBackColorOptions = $.map(initialData.BackColorOptions,
function (item) {
return new BackColorOption(item, self);
}
);
self.BackColorOptions = ko.observableArray(mappedBackColorOptions);
}
ko.applyBindings(new TestViewModel());
型号代码:
string BackColor { get; set; }
SelectListItem[] BackColorOptions
{
get
{
return new[]
{
new SelectListItem{Text = "cc0000"},
new SelectListItem{Text = "ff9900"},
new SelectListItem{Text = "dddd33"},
new SelectListItem{Text = "009900"},
new SelectListItem{Text = "00cccc"},
new SelectListItem{Text = "0066ff"},
new SelectListItem{Text = "9900ff"},
new SelectListItem{Text = "ff00ff"},
};
}
}
上面的代码在 IE (8) 和 Chrome (17) 中按预期工作,但在 FF (10.0.2) 中没有。我基本上是在尝试做一个类似于 GitHub 问题标签的颜色选择器。该视图呈现一组单选按钮,您可以单击以选择颜色。检查收音机时,我将selected
css添加class
到 parent <li>
。css 类导致复选标记图标出现在<li>
.
在 Firefox 中,选定的 css 类仅在用户完成并检查每个单选按钮至少一次后才会应用。我调试并发现这是因为在闭包中计算计算的self.Color
observable的方式。BackColorOption
在第一次检查无线电之前,typeof(self.Color) == 'function'
评估为真。然而,在它被检查之后,typeof(self.Color) == 'string'
评估为真。
typeof(self.Color)
根据 Firebug 和 Chrome 的 js 调试器,这种行为是相同的。然而,FF 中的问题是由于闭包中self.Selected
计算的 observable 中的这一行:BackColorOption
return backColor.toLowerCase() == self.Color;
即使self.Color
是函数而不是字符串,Chrome 和 IE 仍然返回 true。然而火狐没有。当self.Color
是一个函数时,它返回false。这就是为什么在将 css 类添加到图标并出现图标之前,您必须至少检查每个收音机一次<li>
。
我对淘汰赛还是有点陌生,并且可能没有适当地将 viewmodel 属性作为函数调用。我仍然有点不清楚何时使用()
括号以及何时省略它们。还有另一种方法我应该编写self.Selected
计算的可观察对象,这取决于self.Color
计算的可观察对象(在BackColorOption
闭包中)?
更新 1
我能够通过以下方式使其在 FF 10.0.2 中工作:
self.Selected = ko.computed(function () {
var backColor = self.parent.BackColor();
var selfColor = self.Color;
if (typeof (selfColor) === 'function')
selfColor = self.Color();
if (backColor) {
return backColor.toLowerCase() === selfColor;
}
return false;
});
然而,这感觉就像我在与淘汰赛作斗争。它不应该“正常工作”吗?