【发布时间】:2012-03-13 16:51:19
【问题描述】:
查看代码:
<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' />
viewmodel代码:
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 添加到父<li>。 css 类会在<li> 上方显示一个复选标记图标。
在 Firefox 中,选择的 css 类仅在用户完成并检查每个单选按钮至少一次后才会应用。我调试并发现这是因为 self.Color 计算的 observable 在 BackColorOption 闭包中被评估的方式。在第一次检查无线电之前,typeof(self.Color) == 'function' 评估为真。然而,经过检查后,typeof(self.Color) == 'string' 的计算结果为真。
根据 Firebug 和 Chrome 的 js 调试器,typeof(self.Color) 的行为是相同的。然而,FF 中的问题是因为 self.Selected 中的这一行在 BackColorOption 闭包中计算的 observable:
return backColor.toLowerCase() == self.Color;
即使self.Color 是函数而不是字符串,Chrome 和 IE 仍会返回 true。然而火狐没有。当self.Color 是一个函数时,它返回false。这就是为什么在将 css 类添加到 <li> 并出现图标之前,您必须至少检查每个收音机一次。
我对淘汰赛还是有点陌生,并且可能没有适当地将 viewmodel 属性作为函数调用。我仍然有点不清楚何时使用 () 括号以及何时省略它们。是否有另一种方法我应该编写 self.Selected 计算的 observable,这取决于 self.Color 计算的 observable(在 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;
});
但是,这感觉就像我在与淘汰赛作斗争。它不应该“正常工作”吗?
【问题讨论】:
-
你能敲一个 jsfiddle 来证明这一点吗?
-
这是一个小提琴:jsfiddle.net/JUKGh/2
标签: asp.net-mvc knockout.js asp.net-mvc-4 knockout-2.0