Обновить
57
0
Андрей Саломатин@filipovskii_off

Пользователь

Отправить сообщение
Это не фантастика, и это уже придумали. Angular, например, делает именно так.
Дата-биндинг отдельная тема, тут я согласен.

Я понимаю, о чём вы. Да, уже существует множество решений проблем шаблонов. На любой вкус и цвет, и работают они довольно быстро.

По поводу подхода var html = '<img src="' + image +'>"'. Он может быть только временным решением. Библиотеки шаблонов, по сути, делают тоже самое, только эскейпят данные. Вариант сносный, но выглядит скорее как хак.

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

Строки
  1. Получить строку шаблон.

    a). Загрузить AJAX-ом
    б). Найти в DOM элемент, содержащий шаблон, извлечь шаблон оттуда.

  2. Провернуть множество операций со строками. Эскейпить данные вручную.

  3. Вставить получившуюся строку в DOM. Браузер парсит строку, рендерит содержимое.


<template>
  1. Получить содержимое <template>.

    Найти в DOM тег <template> с нужным шаблоном. Его содержимое уже распаршено, с ним можно работать как с любым элементов в DOM.

  2. Подставить данные, используя DOM API. Нет необходимости заботится о вредоностности данных.

  3. Вставить элемент DOM в… DOM. Браузеру не нужно ничего парсить, он сразу рендерит содержимое.

Сложно сказать, какой подход будет быстрее, пока нет бенчмарков. Но вариант с <template> определённо однородней и «чище».

Да, скорость работы DOM пока ещё проблема. Но мы, в случае с <template> работаем на очень ограниченном его «участке».

Уже сейчас все это лаконично и шустро работает, даже без shadow dom.

Shadow DOM не влияет на работу шаблонов.
Какие-то части библиотек всё таки стандартизируют. История jquery и querySelector() это подтверждает. Promises возможно когда-нибудь попадут в стандарт.

Об остальном сложно спорить. Поживём — увидим…
Хотя нет, я не прав. Действительно нужны будут новые библиотеки. Polymer просто одолжил синтаксис своей у Mustache.
Для работы с условиями, циклами и прочим мы по-прежнему можем использовать любимые template-библиотеки, вроде Mustache. <template> просто держит ваш шаблон «на готове», как его заполнять данными — дело ваше.

Polymer используют Mustache совместно с <template> и Object.observe для подстановки данных в шаблоны: polymer data-bindings.
Такого рода стандартизация по-моему будет скорее мешать. Умный ход — выпустить API которое позволяет программистам делать всё что они хотят, а потом взять лучшие практики и сделать их стандартом. Поступать наоборот — риск.

Я надеюсь, если web components пойдут в народ, появятся библиотеки элементов, вроде bootstrap, yui и т.д. У них будут свои, внутренние, стандарты и лучшие практики.
Привычка… В html5 и так можно:

  <img src="bad-url">
По поводу проблем 2 и 3 согласен. Да, кнопки like и +1 действительно показательный кейс. Что вы имеете ввиду под стандартизацией кастомных тегов?

> Содержимое тегов парсится браузером, но не вызывает выполнение скриптов

Вообще скрипты итак не выполняются при вставке с помощью innerHTML.

Я имел ввиду, если браузер загружает документ, в котором есть такой код:

  <template>
    <script>alert(1);</script>
  </template>

alert(1); не выполнится до тех пор, пока мы не сделаем импорт содержимого шаблона:

  var tmpl = document.querySelector('template');
  var tmplBody = document.importNode(tmpl.content);

  document.body.appendChild(tmplBody);
  1. Не совсем понял мысль вашу мысль о Shadow DOM. Приведу ещё один пример его использования.

    Так выглядит разметка строки поиска google.com
    <fieldset class="gbqff gb_j" id="gbqff">
      <legend class="gbxx"></legend>
      <div id="gbfwa" class="gbqfwa ">
        <div id="gbqfqw" class="gbqfqw ">
          <div id="gbqfqwb" class="gbqfqwc">
            <table cellspacing="0" cellpadding="0" id="gs_id0" class="gstl_0 lst-t" style="height: 27px; padding: 0px;">
              <tbody>
                <tr>
                  <td id="gs_ttc0" style="white-space: nowrap;" dir="ltr"></td>
                  <td id="gs_tti0" class="gsib_a">
                    <div id="gs_lc0" style="position: relative;">
                      <input id="gbqfq" class="gbqfif" name="q" type="text" autocomplete="off" value="" style="border: none; padding: 0px; margin: -0.0625em 0px 0px; height: 1.25em; width: 100%; background-image: url(data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw%3D%3D); background-color: transparent; position: absolute; z-index: 6; left: 0px; outline: none; background-position: initial initial; background-repeat: initial initial;" dir="ltr" spellcheck="false">
                      <div class="gbqfif" id="gs_sc0" style="background-color: transparent; color: transparent; padding: 0px; position: absolute; z-index: 2; white-space: pre; visibility: hidden; background-position: initial initial; background-repeat: initial initial;"></div>
                      <input class="gbqfif" disabled="" autocomplete="off" aria-hidden="true" id="gs_taif0" dir="ltr" style="border: none; padding: 0px; margin: 0px; height: auto; width: 100%; position: absolute; z-index: 1; background-color: transparent; -webkit-text-fill-color: silver; color: silver; left: 0px; visibility: hidden;"><input class="gbqfif" disabled="" autocomplete="off" aria-hidden="true" id="gs_htif0" dir="ltr" style="border: none; padding: 0px; margin: 0px; height: auto; width: 100%; position: absolute; z-index: 1; background-color: transparent; -webkit-text-fill-color: silver; color: silver; transition: all 0.218s; -webkit-transition: all 0.218s; opacity: 0; left: 0px; text-align: left;">
                    </div>
                  </td>
                  <td class="gsib_b">
                    <div class="gsst_b" id="gs_st0" style="line-height: 27px;" dir="ltr">
                      <a class="gsst_a" href="javascript:void(0)" aria-label="Listening for "Ok Google"" style="display: none;"><span class="gsri_ha gsst_e" id="gsri_hok0"></span></a><a class="gsst_a" href="javascript:void(0)" aria-label="Search by voice"><span class="gsri_a gsst_e" id="gsri_ok0"></span></a>
                      <div id="chmo">
                        <div id="chm">
                          <div class="chmp">
                            <div class="chmpi chmp"></div>
                          </div>
                          <div style="display: none;">
                            <div class="chma"></div>
                            <div>Not listening. Something went wrong.</div>
                            <div><a>Restart listening</a><a style="padding-left: 10px;">Help</a></div>
                          </div>
                          <div style="display: none;">
                            Hotword detection is off.
                            <div><a>Start listening for "Ok Google"</a></div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </fieldset>
    


    Очень много «низкоуровнего» кода. Shadow DOM позволяет скрыть детали реализации элемента и инкапсулировать его стили, чтобы они не конфликтовали с документом. Таким образом в документе строка поиска будет выглядеть как-то так:

      <div class="google-search"></div>
    


    Или так, с использованием custom elements:

      <google-search></google-search>
    


    Детали реализации будут изолированны и лежать где-то в другом месте. Это похоже на разделение интерфейс/реализация в объектно-ориентированных языках.

  2. Подобие custom elements можно написать самому, тут вы правы. Они уже есть в некоторых фреймворках. Ничего нового, только теперь браузер будет поддерживать это нативно.
  3. <template> это не совсем шаблонизатор. Его задача не в том, чтобы взять данные и подставить их в разметку. Это скорее «хранилище» html кода, который вы планируете использовать не сразу, как только документ загрузится, а позже.

    API у него сводится к одному свойству content. Сомневаюсь что браузеры тут могут накуролесить.

Всё верно, он каждый раз создаёт новые фрагменты документа. Но в отличие от шаблона, shadow tree изолировано от остального DOM, то есть:

  • Добраться до содержимого shadow tree с помощью document.querySelector() и querySelectorAll() нельзя
  • Стили, определённые в документе не распространяются на содержимое (если applyAuthorStyles = false)
  • Стили, определённые в shadow tree не распространяются на документ.

Наружу у «кастомного элемента» торчит только JS API, определённое разработчиком.
Импортируемый документ не должен быть полноценным. Это действительно фрагменты разметки. Импортируемый файл TODO-виджета, например, выглядит так.

Реимпорт не происходит. Полагаю, это один из багов. Импорты работают не так хорошо, как всё остальное.
Могу только догадываться почему назвали именно так. В источниках эта информация не попадалась.

В примерах к этой статье, например здесь (код) и тут (код) я переиспользую самописный элемент <wc-example>, его код лежит здесь.

Получившийся TODO-виджет также можно переиспользовать. Импортим html-файл на страницу, и браузер будет рисовать виджет на месте <x-todo> элементов.

Тег <template> это не совсем темплейтинг. Скорее механизм отложить фрагмненты разметки, пока они не пригодятся. Подставлять данные в содержимое <template> нужно вручную, с помощью js.
В голову сходу приходят три сценария, которые могли бы к этому привести:
1. Использование __slots__ может привести к такой ошибке, при попытке установить атрибут с именем, не перечисленным в __slots__
2. Использование __setattr__, в нём явный raise AttributeError()
3. Использование дескриптора данных, с raise AttributeError() в методе __set__

возможно, есть ещё варианты
Не могу с вами согласиться. Если развить этот пример:
Foo.__dict__["getter_only"].__get__  # <method-wrapper '__get__' of property object at 0x21dd5d0>
Foo.__dict__["getter_only"].__set__  # <method-wrapper '__set__' of property object at 0x21dd5d0>
f = Foo()
f.getter_only = 1                                  # AttributeError 

если бы getter_only был дескриптором не данных, значение записалось бы в __dict__ экземпляра
да, пожалуй, упомянуть действительно стоило
Статья, на мой взгляд, и так разрослась сверх меры. А mro довольно крупная тема, которую я планировал рассмотреть отдельно (вместе с super(), множественным наследованием, и, возможно, метаклассами).
Верно, мой косяк. Спасибо за замечание! Поправил статью.
Спасибо за полезный линк. Насколько я знаю, в python3 протокол атрибутов практически не изменился по сравнению с 2.6. По крайней мере вся информация в этой статье будет актуальна для new-style objects в 2.6. Примеры на python3 — робкая попытка внести небольшой вклад в его популизацию.
2

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Зарегистрирован
Активность