在自定义挖空绑定的init和update之间存储状态的首选方法是什么?

Dre*_*ner 56 knockout.js

目前我使用jQuery数据存储状态为dom元素.

ko.bindingHandlers.customValue = {

    init: function init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var state = { isEditing: false };        
        $(element).focus(function focus() {
            state.isEditing = true;
        }).blur(function blur() {
            state.isEditing = false;            
        }).data("customBinding", state);

    },

    update: function update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        // ignore if updating
        if (!$(element).data("customBinding").isEditing) {
            // handle update if they are not updating                                
        }
    }

};?
Run Code Online (Sandbox Code Playgroud)

是否有更好的地方存储不需要dom的绑定状态?bindingContext可以用于存储绑定的每个实例的状态吗?

RP *_*yer 47

bindingContext是一种可能性,但仅用于将数据从第一次触发绑定传递initupdate第一次.下一次update发射它将不再存在.

存储此类状态的位置实际上有两种选择:

1-正如你所说,在元素上.您可以使用jQuery的$.data或KO包括这样做还有的API ko.utils.domData.get(element, key)ko.utils.domData.set(element, key, value).

2-如果适用,将此类信息放在视图模型中.要显示的标志isEditing在视图模型中不一定不合适.我个人喜欢将这种类型的"元数据"作为子可观察对象,如下所示:

var name = ko.observable("Bob");
name.isEditing = ko.observable(false);
Run Code Online (Sandbox Code Playgroud)

你将能够绑定namename.isEditing.

这有一些优点:

  • 保持视图模型相当干净,因为您没有引入新的顶级属性
  • 保持子观察与其父观察相关(不需要nameIsEditing等)
  • 当使用像sub-observable 这样ko.toJSON的东西变成JSON时,isEditing只需在它的父元素被解包时被删除.因此,您不会将不必要的值发送回服务器.
  • 在这种情况下,它还可以具有在视图模型中可用于其他计算或绑定到UI中的多个元素的优点.


Mic*_*est 8

将数据附加到元素是可以的,并且Knockout在内部使用此方法用于控制流绑定(例如,if,with等).

另一种方法是仅使用该init函数并使用计算的observable来处理更新.我在重复绑定中使用此方法.以下是重要部分:

ko.bindingHandlers['repeat'] = {
    'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        ...
        // set up persistent data
        var lastRepeatCount = 0;
        ...
        ko.computed(function() {
            var repeatCount = ko.utils.unwrapObservable(valueAccessor());
            ...
            // Remove nodes from end if array is shorter
            for (; lastRepeatCount > repeatCount; lastRepeatCount--) {
                ...
            }
            ...
            // Add nodes to end if array is longer (also initially populates nodes)
            for (; lastRepeatCount < repeatCount; lastRepeatCount++) {
                ...
            }
        }, null, {'disposeWhenNodeIsRemoved': placeholder});
        ...
    }
};
Run Code Online (Sandbox Code Playgroud)