【问题标题】:Am I doing this knockout binding incorrectly?我做这个淘汰赛绑定不正确吗?
【发布时间】: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 添加到父&lt;li&gt;。 css 类会在&lt;li&gt; 上方显示一个复选标记图标。

在 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 类添加到 &lt;li&gt; 并出现图标之前,您必须至少检查每个收音机一次。

我对淘汰赛还是有点陌生​​,并且可能没有适当地将 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;
});

但是,这感觉就像我在与淘汰赛作斗争。它不应该“正常工作”吗?

【问题讨论】:

标签: asp.net-mvc knockout.js asp.net-mvc-4 knockout-2.0


【解决方案1】:

KO 中的value 绑定对于单选按钮和复选框来说并不理想。在您的情况下,您需要您的单选按钮具有 value 属性,以便当您单击它们时,该值可用于更新您的 TestViewModel.BackColor observable。

通常使用单选按钮时,您不希望 value 属性在呈现 html 后更改(如果有的话)。

所以,我已将您的 html 模板从使用 value 绑定更改为使用 attr 绑定(html 属性)。这现在只是设置单选按钮的value html 属性。然后checked 绑定使您的TestViewModel.BackColor observable 与选中的单选按钮的value 保持同步。

看这个小提琴: http://jsfiddle.net/m2KQ2/

另外,BackColorOption 函数中的行有错字:

self.Selected = ko.computed(function () {
    var backColor = self.parent.BackColor();
    if (backColor) {
        return backColor.toLowerCase() == self.Color; //<-- should be Color();
    }
    return false;
});

【讨论】:

  • 谢谢埃里克,是的,这行得通。我没有想到使用 attr 绑定而不是值绑定来绑定值。你是对的,我不希望单选按钮的值改变。我确实注意到你的小提琴正在调用 self.Color() 作为一个函数,并相应地更新了我的代码。
猜你喜欢
  • 2013-02-04
  • 1970-01-01
  • 2017-10-28
  • 2013-10-31
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多