KnockoutJS:可写的可计算观察对象没有更新

KnockoutJS: Writable computed observable not updating

本文关键字:对象 更新 观察 可计算 KnockoutJS      更新时间:2023-09-26

我有以下代码,我试图使用一个可写的计算观察对象来验证用户输入,并自动拒绝无效输入。这只是一些测试代码,我试图阻止用户从文本中删除逗号字符。如果用户删除了逗号字符,我将尝试将编辑器重新绑定到先前的值,以覆盖最近的更改。这是否可能使用可写的计算字段?我遇到的问题是,可写的计算绑定仅在加载页面时触发(在手动设置ValidText prop之后)。但是,当用户在编辑器中输入时,我无法让它触发。

代码:

<script type="text/javascript">
    var model = null;
    function EditModel() {
        this.Count = 2;
        var self = this;
        this.ExistingValue = ko.observable("");
        this.ValidText = ko.computed({
            read: function () {
                return self.ExistingValue();
            },
            write: function (text) {
                if (text.split(',').length === self.Count) {
                    self.ExistingValue(text);
                }
            },
            owner: self
        });
    }
    $(document).ready(function () {
        model = new EditModel();
        model.ValidText('@(Model.Text)');
        ko.applyBindings(model);
    });
</script>
<div id="mainContainer">
    <div id="editor" contenteditable="true" class="commentEditBox" data-bind="text: ValidText, valueUpdate: 'afterkeydown'" ></div>
</div> 

最终采用了自定义绑定的想法,并将代码转换为以下内容:

<script type="text/javascript">
    var model = null;
    ko.bindingHandlers.customEditorBinding = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            $(element).on('keydown', function () {
                var observable = valueAccessor();
                observable($(this).text());
            });
        },
        update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var text = ko.utils.unwrapObservable(valueAccessor());
            if (text.split(',').length === model.Count) {
                model.ValidText(text);
                model.PreviousText = text;
                $(element).text(text);
            }
            else {
                 model.ValidText(model.PreviousText);
                $(element).text(model.PreviousText);
            }
        }
    };
    function EditModel() {
        var self = this;
        self.Count = 2;
        self.ValidText = ko.observable("");
        self.PreviousText = null;
    }
    $(document).ready(function () {
        model = new EditModel();
        model.ValidText('This is,a test');
        ko.applyBindings(model);
    });
</script>
<div id="mainContainer">
    <div id="editor" contenteditable="true" class="commentEditBox" data-bind="customEditorBinding:ValidText" ></div>
</div>

好,混淆使用self和这个分开,你已经绑定到一个div使用文本,你试图让它更新时,值的变化。这个html元素没有值,所以它没有触发。

看一下自定义绑定,并将写逻辑移到它的update方法中。

ko.bindingHandlers.yourBindingName = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        // This will be called when the binding is first applied to an element
        // Set up any initial state, event handlers, etc. here
    },
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        // This will be called once when the binding is first applied to an element,
        // and again whenever the associated observable changes value.
        // Update the DOM element based on the supplied values here.
    }
};

在write方法中添加else子句:

else { self.ValidText.notifySubscribers(self.ExistingValue()); }

将强制文本框更新回原始值