【问题标题】:KnockoutJS custom binding calling click event during bind, not on clickKnockoutJS 自定义绑定在绑定期间调用单击事件,而不是在单击时
【发布时间】:2013-04-07 17:42:53
【问题描述】:

我正在尝试使用 knockoutjs 将可观察的人员数组绑定到两列响应式布局与点击事件。

我创建了一个名为 TwoCol 的自定义绑定,它循环遍历数组,并将节点附加到 DOM 以创建我建议的布局,但是当我尝试将它们应用于嵌套在一个自定义绑定中时,单击事件给我带来了麻烦循环。

我玩过很多次,遇到了各种类型的结果,但我现在是在绑定期间调用我的 ~click~ 事件,而不是在点击时。

http://jsfiddle.net/5SPVm/6/

HTML:

<div data-bind="TwoCol: Friends" id="" style="padding: 20px">

JAVASCRIPT:

function FriendsModel() {
    var self = this;
    this.Friends = ko.observableArray();
    this.SelectedFriend = "";
    this.SetSelected = function (person) {
        alert(person);
        self.SelectedFriend = person;
    }
}
function isOdd(num) {
    return num % 2;
}
ko.bindingHandlers.TwoCol = {
    update: function (elem, valueAccessor) {
        var i = 0;
        var rowDiv;
        var vFriends = ko.utils.unwrapObservable(valueAccessor());
        $(elem).html('');
        while (i < vFriends.length) {
            //create row container every other iteration
            if (!isOdd(i)) {
                rowDiv = document.createElement("div");
                $(rowDiv).addClass("row-fluid");
                elem.appendChild(rowDiv);
            }
            //add column for every iteration
            var colDiv = document.createElement("div");
            $(colDiv).addClass("span6");
            rowDiv.appendChild(colDiv);
            //actual code has fairly complex button html here
            var htmlDiv = document.createElement("div");
            var htmlButton = vFriends[i]
            htmlDiv.innerHTML = htmlButton;
            colDiv.appendChild(htmlDiv);
            //i think i need to add the event to the template too?
            //$(htmlDiv).attr("data-bind", "click: { alert: $data }")
            //it seems that the SetSelected Method is called while looping
            ko.applyBindingsToDescendants(htmlDiv, { click: friends.SetSelected(vFriends[i]) });
            i++;
        }
        return { controlsDescendantBindings: true };
    }
}

var friends = new FriendsModel();
friends.Friends.push('bob');
friends.Friends.push('rob');
friends.Friends.push('mob');
friends.Friends.push('lob');
ko.applyBindings(friends);

【问题讨论】:

  • 小提琴中的代码与您在此处的代码不匹配,并且有几个语法错误
  • 好的,我现在点击更新(并附加 /6/),再试一次?

标签: javascript knockout.js


【解决方案1】:

我认为您没有正确使用ko.applyBindingsToDescendants。我承认我对您代码中某些值的含义有些困惑,因此我可能对某些内容进行了错误的解释。

这是一个小提琴,我认为它按您的预期工作: http://jsfiddle.net/5SPVm/7/ http://jsfiddle.net/5SPVm/8/

请注意,如果手动控制后代绑定 (return { controlsDescendantBindings: true };),则需要在 init 回调中进行设置,而不是更新。更新回调为时已晚。

更改的简要说明(已编辑)

  1. controlsDescendantBindings 移动到init 绑定回调中
  2. 将必要的参数名称添加到绑定参数列表以访问其他值。
  3. 我重新启用了 html.attr 调用。请注意,现在,因为绑定上下文设置为实际项目,SetSelected 方法不再存在于该级别,因此需要使用$parent.SetSelected

            $(htmlDiv).attr("data-bind", "click: $parent.SetSelected")
    
  4. 修复了ko.applyBindingsToDescendants 调用。此方法采用从当前绑定上下文创建的绑定上下文,并且还采用要应用绑定的元素。您不想重新应用绑定,这就是为什么整个事情都需要在 init 处理程序中。

            var childBindingContext = bindingContext.createChildContext(vFriends[i]);
        ko.applyBindingsToDescendants(childBindingContext, colDiv);
    

【讨论】:

  • 谢谢!这很好用,但在我的生产场景中,所有项目都是在初始绑定之后添加的,并且在推送它们时似乎没有调用 init。你能帮我在初始化和更新之间拆分代码以适应这种情况吗?我“摆弄”了你的小提琴,但这只是让我头疼。
  • 我错了 applyBindingsToDescendants 在 init 中。我会更新答案。 controlDescendantsBindings:true 确实 需要在 init 中。更新中其他一切都很好。 jsfiddle.net/5SPVm/8.
猜你喜欢
  • 2020-10-16
  • 1970-01-01
  • 2011-08-25
  • 2013-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多