Как предотвратить слишком глубокое копирование шаблоном jQuery массива строк в рекурсивном шаблоне «отражения»? - PullRequest
0 голосов
/ 15 сентября 2011

full jsFiddle Пример

Из того, что я выяснил в моем последнем вопросе о $.tmpl, передача массива строк в шаблон, содержащий {{each}}, приведет к тому, что шаблон будет проходить по каждой строке в массиве как массив символов, потому что tmpl уже неявно зацикливается на массивах. К сожалению, это означает, что если я уже нахожусь в заданном шаблоне и рекурсивно вызываю этот шаблон снова для массива строк (подобъекты работают нормально), я пропускаю уровень рекурсии и пытаюсь шаблонировать каждую строку в массиве вместо шаблонный сам массив.

Если я рекурсивно шаблонизирую объект с помощью {{каждого}} (в основном это отражение), как я могу предотвратить возникновение этого неявного цикла массива?

HTML

<div class="results"></div>
<script id="reflectTemplate" type="text/x-jquery-tmpl"> 
    <ul>
        {{each(i, prop) $data}}
        {{if $data.hasOwnProperty(i)}}
        <li>
            ${i}:
            {{if $item.shouldDigDeeper(prop)}}
            {{tmpl(prop, { shouldDigDeeper: $item.shouldDigDeeper, formatDisplay: $item.formatDisplay }) "#reflectTemplate"}}
            {{else}}
            ${$item.formatDisplay(prop)}
            {{/if}}
        </li>
        {{/if}}
        {{/each}}
    </ul>
</script>

JavaScript

var data = {
        test2: "abc",
        test3: [ "abc", "123", "def", "456" ]
    },
    templateFunctions = {
        shouldDigDeeper: function(itemToCheck) {
            return null !== itemToCheck && "object" === typeof(itemToCheck);
        },
        formatDisplay: function(propertyValue) {
            var result = propertyValue;    
            if (null === result) {
                result = "null";
            }
            else if ("string" === typeof (propertyValue)) {
                result = "\"" + result + "\"";
            }
            return result;
        }
    };

$("#reflectTemplate").tmpl(data, templateFunctions).appendTo($(".results"));

Фактический объем производства

<ul>
    <li>test2: "abc" </li>
    <li>test3:
        <ul>
            <li>0: "a" </li>
            <li>1: "b" </li>
            <li>2: "c" </li>
        </ul>
        ...
        <ul>
            <li>0: "4" </li>
            <li>1: "5" </li>
            <li>2: "6" </li>
        </ul>
    </li>
</ul>

желаемый выход

<ul>
    <li>test2: "abc" </li>
    <li>test3:
        <ul>
            <li>0: "abc" </li>
            ...
            <li>1: "456" </li>
        </ul>
    </li>
</ul>

1 Ответ

0 голосов
/ 16 сентября 2011

В случае, если @ mblase75 прав (читай: это невозможно), и никто больше не придумал ничего другого, вот обходной путь, который я придумала.

Пример jsFiddle

Поскольку tmpl предварительно перепрыгивает уровень глубже в массивы, я только что придумал систему шаблонов, которые отскакивают друг от друга при появлении массива.Один шаблон обрабатывает только элементы массива, в то же время разрешая вложенные объекты / массивы в нем (кажется).Дублирование немного грубое, но, похоже, оно подходит для даже сумасшедших вложенных массивов.

HTML

<div class="results"></div>
<script id="arrayDisplayTemplate" type="text/x-jquery-tmpl">
<li>
    {{if null !== $data && "object" === typeof ($data)}}
        {{if $data instanceof Array}}
    [
    <ul>
        {{tmpl($data, { formatDisplay: $item.formatDisplay }) "#arrayItemTemplate"}}
    </ul>
    ]
        {{else}}
    {{tmpl($data, { formatDisplay: $item.formatDisplay }) "#reflectTemplate"}}
        {{/if}}
    {{else}}
    ${$item.formatDisplay($data)}
    {{/if}}
</li>
</script>
<script id="reflectTemplate" type="text/x-jquery-tmpl"> 
<ul>
    {{each(i, prop) $data}}
    {{if $data.hasOwnProperty(i)}}
    <li>
        ${i}:
        {{if null !== prop && "object" === typeof (prop)}}
            {{if prop instanceof Array}}
        [
        <ul>
            {{tmpl(prop, { formatDisplay: $item.formatDisplay }) "#arrayDisplayTemplate"}}
        </ul>
        ]
            {{else}}
        {{tmpl(prop, { formatDisplay: $item.formatDisplay }) "#reflectTemplate"}}
            {{/if}}
        {{else}}
        ${$item.formatDisplay(prop)}
        {{/if}}
    </li>
    {{/if}}
    {{/each}}
</ul>
</script>

JavaScript

var data = {
    test1: 123,
    test2: { w: [ "some", "string", "array" ], x: 1, y: 2, z: "abc" },
    test3: [ "abc", "123", "def", "456" ],
    test4: null
},
    templateFunctions = {
        formatDisplay: function(propertyValue) {
            var propertyType = typeof (propertyValue),
                result = propertyValue;

            if (null === result) {
                result = "null";
            }
            else if ("string" === propertyType) {
                result = "\"" + result + "\"";
            }
            return result;
        }
    };

$("#reflectTemplate").tmpl(data, templateFunctions).appendTo($(".results"));
...