KnockoutJS-组件-多个实例

KnockoutJS - Components - Multiple instances

本文关键字:实例 组件 KnockoutJS-      更新时间:2023-09-26

我有这个KnockoutJS组件,我需要在同一页面上有多个实例。我遇到了不同实例似乎共享可观察属性的问题。因此,如果其中一个文本区域被更新,那么同一页面上的其他文本区域也会被更新。

我试着在不同的文本区域设置唯一的id作为测试,但这并没有解决问题

这是我的组件代码:

ko.components.register('note-editor', {
    viewModel: (params) => {
        var self = this;
        this.id = uid.new('note-editor-');
        this.title = ko.observable(params && params.title || '');
        this.titleClass = ko.observable(params && params.titleClass || '');
        this.expandTooltip = ko.observable(params && params.expandTooltip || '');
        this.numberOfCharactersLeft = ko.observable(params && params.numberOfCharactersLeft || '');
        this.limitCharacters = ko.observable(params && params.limitCharacters || 1000);
        this.showNote = params.showNote;
        this.notes = params.notes;
        this.showIcon = ko.computed(() => {
            return self.notes() != undefined && self.notes() != '';
        });
        this.notesCount = ko.computed(() => {
            var value = self.notes(),
                charLimit = self.limitCharacters();
            if (value) {
                var characters = charLimit - value.length;
                if (characters < 0) {
                    return 0;
                }
                return characters;
            }
            return charLimit;
        });
    },
    template: '<div data-bind="text: title, attr: { class: titleClass }"></div>'
    + '<div tabindex="1" data-bind="toggleButton: showNote, attr: { title: expandTooltip }" class="toggleButton"></div><img data-bind="visible: showIcon" src="https://placeholdit.imgix.net/~text?txtsize=5&txt=30%C3%9730&w=20&h=20" style="margin-bottom: -7px" />'
    + '<div class="note-counter" data-bind="visible: showNote, style: { fontWeight: notesCount() == 0 ? ''bold'' : '''' }">'
    + '<span data-bind="text: notesCount()" > </span><span data-bind="text: numberOfCharactersLeft"></span>'
    + '</div>'
    + '<textarea data-bind="visible: showNote, value: notes, valueUpdate: [''input'', ''afterkeydown''], limitCharacters: limitCharacters, attr: { id: id, name: id }" tabindex="1"></textarea>'
});

完成后,视图模型和模板将在外部文件中。

如果我把组件的3-4个实例放在上面,它似乎只是最后一个"工作"的实例。

尝试用谷歌搜索这个问题几个小时,但没有成功:(

希望有人能告诉我正确的方法!

因此,经过数小时后,我找到了解决方案。我不得不使用createViewModel工厂模式。如果不使用,那么视图模型将被用作单例实例,这就是我的问题。

我真的不喜欢singleton模式是默认的。如果需要的话,我可以使用createViewModel工厂模式来实现singleton模式。

无论如何,它已经解决了,所以我想我应该在这里发布我的解决方案,以供其他人寻找答案:)

function noteViewModel(params) {
    var self = this;
    self.id = uid.new('note-editor-');
    self.title = ko.observable(params && params.title || '');
    self.titleClass = ko.observable(params && params.titleClass || '');
    self.expandTooltip = ko.observable(params && params.expandTooltip || '');
    self.numberOfCharactersLeft = ko.observable(params && params.numberOfCharactersLeft || '');
    self.limitCharacters = ko.observable(params && params.limitCharacters || 1000);
    self.showNote = params.showNote;
    self.editorNotes = params.notes;
    self.showIcon = ko.computed(() => {
        return self.editorNotes() != undefined && self.editorNotes() != '';
    });
    self.notesCount = ko.computed(() => {
        var value = self.editorNotes(),
            charLimit = self.limitCharacters();
        if (value) {
            var characters = charLimit - value.length;
            if (characters < 0) {
                return 0;
            }
            return characters;
        }
        return charLimit;
    });
}
ko.components.register('note-editor', {
    viewModel: (params) => {
        createViewModel: return new noteViewModel(params);
    },
    template: '<div data-bind="text: title, attr: { class: titleClass }"></div>'
    + '<div tabindex="1" data-bind="toggleButton: showNote, attr: { title: expandTooltip }" class="toggleButton"></div><img data-bind="visible: showIcon" src="https://placeholdit.imgix.net/~text?txtsize=5&txt=30%C3%9730&w=20&h=20" style="margin-bottom: -7px" />'
    + '<div class="note-counter" data-bind="visible: showNote, style: { fontWeight: notesCount() == 0 ? ''bold'' : '''' }">'
    + '<span data-bind="text: notesCount()" > </span><span data-bind="text: numberOfCharactersLeft"></span>'
    + '</div>'
    + '<textarea data-bind="visible: showNote, value: editorNotes, valueUpdate: [''input'', ''afterkeydown''], limitCharacters: limitCharacters, attr: { id: id, name: id }" tabindex="1"></textarea>'
});

享受:)