KnockoutJS - 组件 - 多个实例

时间:2016-05-19 10:53:54

标签: javascript knockout.js

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

我试图在不同的textareas上设置唯一的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>'
});

完成后,viewmodel和模板将位于外部文件中。

如果我在上面放置了3-4个组件的实例,那么它似乎只是“工作”的最后一个实例。

试图谷歌这个问题几个小时,但没有成功:(

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

1 个答案:

答案 0 :(得分:0)

所以,经过无数个小时我找到了解决方案。我不得不使用createViewModel工厂模式。如果没有使用,那么viewmodel将被用作单例实例,这就是我的问题。

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

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

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>'
});

享受:)