2

我正在尝试使用淘汰赛来创建一个 html 编辑器/预览器。我使用单个可观察对象设置了一个简单的测试,如下所示:

JS:

var ViewModel = function() {
    this.content = ko.observable("<div data-bind=\"text: 'testext'\"></div>");
};

ko.bindingHandlers.bindHTML = {
    'init': function () {
    },
    'update': function (element, valueAccessor) {                         
        ko.utils.setHtml(element, valueAccessor());
    }
}

ko.applyBindings(new ViewModel());

HTML:

<input type="text" data-bind="value: content">

当页面首次加载时,这似乎工作正常,显示一个带有“testtext”的div,但是一旦我将输入字段编辑为 <div data-bind=\"text: 'testext2'\"></div>绑定不起作用!

这是淘汰赛的限制,还是我做错了什么?有没有办法进行重新绑定?

此处提供 JSFiddle:http: //jsfiddle.net/Q9LAA/

4

2 回答 2

4

有一个html绑定可以自动为您插入 html(我更喜欢这个而不是 using setHtml),但它不会评估插入的 html 上的绑定,您必须在生成的 html 上重新应用绑定(这就是您将需要自定义绑定)。

ko.bindingHandlers.bindHTML = {
    init: function () {
        // we will handle the bindings of any descendants
        return { controlsDescendantBindings: true };
    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        // must read the value so it will update on changes to the value
        var value = ko.utils.unwrapObservable(valueAccessor());
        // create the child html using the value
        ko.applyBindingsToNode(element, { html: value });
        // apply bindings on the created html
        ko.applyBindingsToDescendants(bindingContext, element);
    }
};

这是一个更新的小提琴,展示了它的使用。

于 2013-12-29T02:26:48.633 回答
1

如果我理解正确,您想使用类似 Knockouthtml绑定的东西,但您尝试绑定的 HTML 包含绑定。问题是您的 HTML 已加载,但 Knockout 不会自动执行applyBindings()更改后的 HTML。

所以你想要的是:

ko.bindingHandlers.bindHTML = {
    init: function () {
        // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
        return { 'controlsDescendantBindings': true };
    },
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // setHtml will unwrap the value if needed
        ko.utils.setHtml(element, valueAccessor());

        var elementsToAdd = element.children;

        for (var i = 0; i < elementsToAdd.length; i++) {
            ko.cleanNode(elementsToAdd[i]); //Clean node from Knockout bindings
            ko.applyBindings(bindingContext, elementsToAdd[i]);
        }
    }
};

我使用for循环遍历要附加的 html 元素的原因是因为假设您要使用bindHTMLbinding 进行附加:

<input type="text" data-bind="value: 'watermelon'" />
<input type="text" data-bind="value: 'orange'" />

使用for循环,每个input元素都将被正确绑定。

这是您更新和工作的JSFiddle

注意:不要做我下面显示的事情。

您可能很想对ko.applyBindings()具有绑定的元素执行操作bindHTML,以自动绑定其所有子元素。这是一个非常糟糕的主意!

如果你这样做,你将进入一个无限循环,因为你会要求淘汰赛一次又一次地执行 bindHTML。这是一个无限递归循环!

于 2015-03-24T13:04:38.533 回答