JsRender/JsViews: как заставить {for} работать с массивами подклассов

Я создал подкласс Array (используя TypeScript), чтобы иметь возможность добавлять в массив дополнительные функции. См. код ниже.

С тех пор я заметил, что тег {for} JsRender/JsViews больше не работает. Я также заметил, что JsRender/JsViews использует $.isArray(...) для перебора массивов, что возвращает false для массивов подклассов.

Когда я изменяю код JsRender/JsViews для использования (data instanceof Array), он работает.

Есть ли другой способ (без изменения кода JsRender/JsViews) заставить массивы подклассов работать с тегом JsRender/JsViews {for}?

Машинопись:

module MyModule {
    export class Collection<T> implements Array<T> {
        constructor() {
            Array.apply(this, arguments);
            return new Array();
        }

        length: number;
        toString(): string { return ""; }
        //... All other Array properties/methods
    }

    // replace dummy declarations with the real thing
    Collection['prototype'] = new Array();
}

Сгенерированный Javascript:

var MyModule;
(function (MyModule) {
    var Collection = (function () {
        function Collection() {
            Array.apply(this, arguments);
            return new Array();
        }

        Collection.prototype.toString = function () { return ""; };
        //... All other Array properties/methods

        return Collection;
    })();
    MyModule.Collection = Collection;

    // replace dummy declarations with the real thing
    Collection['prototype'] = new Array();
})(MyModule|| (MyModule= {}));

person Erik v O.    schedule 11.03.2015    source источник
comment
Кажется, это работает для меня. Используете ли вы последние версии jQuery и JsView?   -  person BorisMoore    schedule 11.03.2015
comment
Я использовал JQuery 1.9.1. Я обновился до 2.1.3, но все равно не работает. Я только что понял, что проблема немного сложнее. Причина, по которой я разделил Array на подкласс Collection‹T›, заключается в том, что я также могу создать подкласс Collection‹T›. Например: class NumberCollection extends Collection<number>. Я создал JsFiddle, чтобы проиллюстрировать проблему. При использовании Collection это работает, а при использовании SubclassedCollection — нет. Как я упоминал выше: я заставил его работать при изменении JsView, чтобы использовать (data instanceof Array) вместо $.isArray(data).   -  person Erik v O.    schedule 12.03.2015


Ответы (1)


Ваша SubclassedCollection не является массивом JavaScript (точно так же, как объект jQuery не является массивом JavaScript). В отличие от вашей коллекции, она возвращает "[object Object]" из Object.prototype.toString.call(ob), а не "[object Array]".

Одним из возможных подходов может быть использование функции:

function toArray(ob) {
    return Array.prototype.slice.call(ob);
}

и либо написать

MyModule.ViewModel = { Coll: toArray(collection2) };

или же зарегистрируйте toArray в качестве помощника (~toArray) или преобразователя ("toArray"), а затем напишите свой шаблон как:

{{for ~toArray(Coll)}}

(или альтернативно {{for Coll convert=~toArray}} или {{for Coll convert="toArray"}}).

Вот обновленная версия вашего jsfiddle: http://jsfiddle.net/16L670re/

person BorisMoore    schedule 12.03.2015