Mustache.js: Доступ к родительской области

Созданный на 11 дек. 2014  ·  18Комментарии  ·  Источник: janl/mustache.js

Доступ к родительской области

Учитывая :

node = {
  id: 1,
  children : [
      { id : 2 },
      { id : 3 }
  ]
}

И следующий шаблон:

{{ id }} {# will output node.id #}
{{#children}}
    {{children.id}}  {# will output node.children[i].id #}
    {{id}}  {# will also output node.children[i].id #}
{{/children}}

Как бы то ни было, иногда вам нужно получить доступ к родительскому свойству (например, в модели вложенного узла).
Его можно легко реализовать, например, используя "../" для получения родительской области видимости.

Бывший :

{{ id }} {# will output node.id #}
{{#children}}
    {{children.id}}  {# will output node.children[i].id #}
    {{id}}  {# will also output node.children[i].id #}
    {{ ../id }}  {# will output node.id #}
{{/children}}

Для этого:

  Context.prototype.lookup = function (name) {
    var cache = this.cache;

    var value;
    if (name in cache) {
      console.log(name + ' found');
      value = cache[name];
    } else {
      var context = this, names, index;

      while (context) {
        if (name.indexOf('.') > 0) {
          value = context.view;
          names = name.split('.');
          index = 0;

          while (value != null && index < names.length)
            value = value[names[index++]];
        } else if(name.match(/^\.\.\//)) {
          name = name.replace(/^\.\.\//, '');
        } else {
          value = context.view[name];
        }

        if (value != null)
          break;

        context = context.parent;
      }

      cache[name] = value;
    }

    if (isFunction(value))
      value = value.call(this.view);

    return value;
  };
Future Plugin

Самый полезный комментарий

Правильно. Совсем забыл про руль.

Давайте потеряем пользователей из-за руля.
Это приемлемое дизайнерское решение.

Все 18 Комментарий

Этого нет в спецификациях mustache , не так ли? Для этого нет обходного пути? Я удивлен, что никто раньше не сталкивался с этим ограничением.

Я согласен, что часто требуется доступ к вещам в родительской области. Мой прагматичный подход всегда заключался в том, чтобы избегать неоднозначных названий свойств. У меня это работает долгое время, хотя часто приводит к появлению странных объектов.

С другой стороны, если говорить об опыте работы с рулем; наличие этой способности может соблазнить людей создавать безумно запутанное разрешение родительской области видимости: {{../../../id}} намного сложнее понять, чем {{movieId}} .

Это правда, что использование "../" может привести к нечитаемости. Но с другой стороны, использование caml для разрешения parent не может быть достигнуто, поскольку вы можете иметь caml в локальной области. Более того, я думаю, что определение ключевого слова для доступа к родителю не будет уважать философию Усы.

честно говоря, я не мог прийти к более простой и лучшей идее, чем использование представления каталога.

Да, избегание неоднозначных имен свойств также приводит к созданию более удобочитаемых / подробных шаблонов. Но я понимаю, почему некоторым нравится эта функция.

Как насчет написания отдельного пакета, который изменяет внутреннюю работу mustache.js чтобы добавить желаемую функцию? Вроде как плагин.

Честно говоря, я не вижу, чтобы это происходило, кроме как через плагин или прагму. И API плагинов, похоже, сейчас не в приоритете.

Я немного об этом подумал ...

Я считаю, что философия Moustache заключается не в том, чтобы передавать данные "как есть" в средство визуализации, а в том, чтобы заранее "подготовить" их в представление. Тогда у вас будет свойство parentId в ваших узлах.

Также проще читать и поддерживать шаблоны с более подробными переменными:

{{ id }}
{{#children}}
    {{children.id}}
    {{id}}
{{/children}}

До и после

{{ nodeId }}
{{#children}}
    {{ nodeId }}
    {{ parentId }}
{{/children}}

Актуально: http://stackoverflow.com/questions/4067093/mustache-read-variables-from-parent-section-in-child-section

(извини, что вызываю тебя @bobthecow , но я всегда ценю твою мудрость в усах: smile :)

вы уже можете подняться, поэтому все, что нужно сделать для решения проблемы, показанной с первым шаблоном, - это обернуть данные временным объектом {node: ... } , обернуть шаблон с помощью {{#node}}...{{/node}} а затем {{node.id}} часть может работать. вам не нужно (и не будет) изменять существующие данные таким образом, и вы можете добавить оба этих "JIT" в качестве to_html() шаблона ...

очень похоже на временный обходной путь. Он также работает только с упрощенной двухуровневой моделью, где вы можете решить с помощью конверта для внешнего слоя. Но что делать, если модель глубже? что чувствует жонглирование.

Часто мне нужно связать модель, которую я получаю из нижних уровней данных, и моя задача - представить ее - в какой бы форме я ни получил ее из инфра. Предложение здесь состоит в том, что я должен рекурсивно преобразовать модель полностью в презентабельное состояние - что здесь будет считаться redable property names .
Это не соответствует действительности ...
Да, правда, он связывает шаблон с моделью. Но можете ли вы показать мне шаблон, который не связан с конкретными модельными правилами? Все шаблоны по определению созданы для визуализации определенной модели.
Другой уровень перемещает уровень определения на один шаг назад и требует уровня перевода, который требует много усилий и не всегда необходим.

ИМХО, я думаю, что инструмент должен оставлять выбор пользователю, а не навязывать самоуверенные правила.

Для читателей пример того, что предлагает @rndme :

const Mustache = require('mustache')

var view = {
  node: {
    id: 5,
    children: [ { id: 6 }, { id: 7 } ]
  }
}

const template = `
{{#node}}
  children:
  {{#children}}

    id: {{ id }}
    parentId: {{ node.id }}
  {{/children}}
{{/node}}
`

const output = Mustache.render(template, view)
console.log(output)

  children:

    id: 6
    parentId: 5

    id: 7
    parentId: 5

Использование следующего шаблона не работает с latest , но _ он должен работать_, imo.

const template = `
  children:
  {{#node.children}}

    id: {{ id }}
    parentId: {{ node.id }}
  {{/node.children}}
`

Да, правда, он связывает шаблон с моделью. Но можете ли вы показать мне шаблон, который не связан с конкретными модельными правилами? Все шаблоны по определению созданы для визуализации определенной модели.
Другой уровень перемещает уровень определения на один шаг назад и требует уровня перевода, что утомительно и не всегда необходимо.

Афайк, философия усов всегда заключалась в том, что вы генерируете представление, которое передается в шаблон, а не передаете модель напрямую.

@osher Можете ли вы показать нам пример, который вы не можете легко решить с помощью упомянутого выше

Я попытаюсь предоставить фрагменты позже, но в основном - с трехуровневым вложением это не сработает, потому что вы не можете обернуть средний уровень - вам нужно преобразовать источник в обработанное представление.
Вы сможете получить доступ к обернутому верхнему уровню, но у вас нет решения для среднего уровня.

Возьмем, к примеру, чванливый документ, где у вас есть корневой уровень, уровень пути, уровень глагола (и есть еще кое-что, но давайте остановимся на этом). На каждом уровне можно указать настраиваемую директиву - x-uses , которая является директивой DI для уровня реализации.

Предположим, вы хотите сгенерировать HTML-документы из этого чванливого документа.
Вам нужна плоская таблица, в которой для каждого обработчика операции (уровня глагола) указывается DI, который он принимает, и от какого уровня он его наследует.
Хотя вся информация заложена в документах чванства - теперь у вас есть проблема.

Следующий.
Попробуйте использовать усы для генерации кода, реализующего API, описанный в документе, который возвращает фиктивные ответы на основе ответа операции по умолчанию.
Попробуйте сгенерировать доклеты, которые описывают, что разработчик, реализующий замену фиктивного ответа реальной логикой, должен ожидать в своем контексте DI, и конкретизирует, на каком уровне он его получает.
Такой же...

Не классическая генерация HTML - да. но кто сказал, что усы только для HTML? это механизм создания шаблонов, и генерация кода обычно реализуется с использованием таких механизмов шаблонов;)

вы не передаете модель напрямую.

это должен быть выбор пользователя, а не ограничение / ограничение

Приведу еще один пример, и я постараюсь сделать это, не выдавая секретного соуса.

Предположим, что существует древовидная структура данных, описывающая активы, принадлежащие игроку в стратегической игре.
Дерево может состоять примерно из 5 уровней, например:
Aliance -> Empire -> City -> Army -> Troops

Каждый уровень может предоставлять бонус-модификатор, например, или бонус атаки, бонус защиты, бонус здоровья и т. Д.
Модификаторы, относящиеся к одной и той же статистике, описываются одним и тем же именем на всех уровнях (в основном потому, что они вычисляются рекурсивно).
Вам нужно использовать механизм шаблонов, чтобы представить боевой симулятор, который должен помочь игрокам выбрать, какая армия является идеальной армией для данной задачи, отображая боевые характеристики войск в армии, которые находятся на самых нижних уровнях, но собирают битвы. модификаторы, названные одним и тем же именем атрибута в дереве.
Это очень упрощенно, но основано на реальной истории, когда другие инструменты решали проблему с большой легкостью, не требуя среднего уровня перевода.

Я добавлю сложности: иногда армии распределяются в оперативной группе уровня Альянса.
Alliance -> Rally -> Troops
Инструмент должен быть достаточно универсальным (простой рекурсивным) и не зависеть от конкретных уровней.

Решил с какими усами назову частичками, только усами не пользовался ...

@osher сказал:

это должен быть выбор пользователя, а не ограничение / ограничение

Несомненно, у усов есть свое мнение. Философия «шаблонов без логики» накладывает множество ограничений на шаблоны, этот факт часто требует подготовки данных / модели перед передачей их в шаблон для рендеринга. Если это не соответствует вашим потребностям, есть альтернативы, которые могут быть лучше, такие как руль или даже lodash.template, и это лишь некоторые из них.

Правильно. Совсем забыл про руль.

Давайте потеряем пользователей из-за руля.
Это приемлемое дизайнерское решение.

Я почти уверен, что @osher был саркастичен, когда сказал: «Это приемлемое дизайнерское решение», но от этой темы отказались с 2016 года. Что происходит? Похоже, что этого вопроса избегают в этом репозитории JavaScript, а также в основном репозитории:
https://github.com/mustache/mustache.github.com/issues/103

Я, например, считаю, что возможность ссылаться на родительскую область видимости лишена логики и не должна противоречить идеалам усов.

Мне нравится идея всегда иметь доступ к корневой области с помощью символа, такого как "../" в начале:

Mustache.render('{{a1}}{{#a}}{{b.c}}{{../a1}}{{/a}}',{"a":{"b":{"c":"x1"}},"a1":"x2"})
"x2x1"

Я бы хотел, чтобы это отображало «x2x1x2», но оно опускает последнее, потому что это не так, как это работает.
Я подумал, что рекомендую использовать что-то вроде JSONPath: https://goessner.net/articles/JsonPath/index.html#e2, однако, в отличие от XPath для XML, он не рекомендует / не реализует родительский оператор, на что я надеялся за.

Возможно, Mustache мог бы просто попытаться сохранить совместимость с ручками и использовать синтаксис ../ для родительского контекста?

AFAIK, handlebars - это только JS, в то время как mustache использует один и тот же синтаксис во многих средах, например PHP. Если вы хотите изменить синтаксис усов, вам нужно будет убедить все другие реализации, отличные от js, сделать то же самое; сложная задача. Кроме того, при изменении кода JS я обнаружил, что подняться «на один уровень» проблематично, хотя я добавил в свою вилку способ возврата к корневому каталогу , что было довольно просто реализовать ...

Что-нибудь по этому поводу?

Также должна быть документация и рекомендации по стилю для ситуаций, когда точечная нотация не является обязательной.

view = { wrap: { txt: "test" } };
{{#wrap}}
  {{wrap.txt}} {{! Should I use this?}}
  {{txt}} {{! Or this?}}
{{/wrap}}

Подробнее здесь: https://stackoverflow.com/q/62166467/5637701

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

kuldeepdhaka picture kuldeepdhaka  ·  9Комментарии

connor11528 picture connor11528  ·  3Комментарии

chlab picture chlab  ·  11Комментарии

Immortalin picture Immortalin  ·  12Комментарии

zekth picture zekth  ·  18Комментарии