- PVSM.RU - https://www.pvsm.ru -
Если вы кого-нибудь спросите, на чем он делает клиентскую сторону своих приложений сегодня, этот человек наверняка ответит, что использует какой-нибудь хипстерский JS-фреймворк, вроде Angular, Ember, Knockout, Backbone или Polymer (смотрите сайт TodoMVC [1]).
У большинства этих фреймворков есть «отличная» возможность, которая позволяет вам «легко» ссылаться на какую-либо информацию, используя дата-биндинги. Они выглядят примерно так:
<!-- Knockout -->
<p>Имя: <input data-bind="value: firstName" /></p>
<p>Фамилия: <input data-bind="value: lastName" /></p>
<h2>Привет, <span data-bind="text: fullName"> </span>!</h2>
<!-- Angular -->
<ul class="phones">
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp">
<span>{{phone.name}}</span>
<p>{{phone.snippet}}</p>
</li>
</ul>
<!-- Ember -->
<div>
<label>Имя:</label>
{{input type="text" value=name placeholder="Введите ваше имя"}}
</div>
<div class="text">
<h1>Меня зовут {{name}} и я хочу выучить Ember!</h1>
</div>
Не смотря на то, что синтаксис немного варьируется, все они делают одно и то же. Они дают вам возможность встроить некоторые выражения в ваш HTML, которые «магически обрабатываются» фреймворком. Это означает — никаких ручных манипуляций DOM; вы можете писать красиво сформированный HTML внутри этих выражений и фреймворк сделает всю мирскую работу (вроде создания узлов, соединения обработчиков событий и обновления DOM при каких-либо изменениях моделей). Звучит это все конечно круто и не сложно заметить как все поддаются мейнстриму и разрабатывают этим путем.
Однако, получается, что все не так, как рекламируется; в подобном подходе есть существенные недостатки, которые остаются незамеченными, пока вы не пытаетесь сделать что-то сложное.
Там где я работаю, мы строим прототипы на многих из этих новых технологий чтобы определиться с ними для новых версий наших продуктов. Такое ощущение, что каждый разработчик, что использует один из этих модных фрейморков борется с ними и мы тратим кучу времени отлаживая проблемы или перекапывая StackOverflow в поисках решений элементарных (казалось бы) задач.
Некоторые из разочарований…
Из-за того, что эти биндинги не являются настоящими HTML-конструкциями, вы не получите никакой пользы от использования ваших инструментов с ними. Ни подсветки, ни авто-завершения кода, ни статического анализа или проверки типов. Скорее всего, в вашем HTML-редакторе эти выражения — просто строки.
Вы начнете с биндинга параметров вроде {{ name }}, но скоро окажется, что ваши выражения вырастают в сложный бардак. Вы поймете, что встроенная функциональность — не совсем то, что вам нужно и начнете гнуть свой фреймворк под дерьмо вроде этого [2], используя функцию JavaScript, которая возвращает функцию просто для применения фильтра с динамическим именем:
<tr
ng-show="banners"
ng-repeat="banner in banners.data"
>
<td ng-repeat="col in banner">
{{ col | dynamicFilter : banners.cols[$index].formatter }}
</td>
</tr>
<script>
myApp.filter('dynamicFilter', function ($filter) {
return function (value, filterName) {
if (Formatters[filterName])
return Formatters[filterName](value);
else
return value;
};
});
</script>
После того, как ваши биндинги будут становиться сложнее, вы увидите, что они редко работают с первого раза. Вы закончите игрой в отладку дробовиком, твикая ваше выражение и перезагружая, надеясь увидеть правильную работу (это реально дерьмово, если у вас очень длинный цикл для возвращения в корректную точку тестирования, как например вручную делая логи вашего приложения).
Когда ваши биндинги работают неправильно, чаще всего вы не увидите ничего. Если вам повезет, вы увидите ошибку JavaScript. Если так, то она вам скажет что-то вроде «e is not a function» и даст вам весь стэк, который на 100 фреймов в глубине вашего фреймворка и ни одна его часть не ссылается на ваш HTML биндинг.
Вы не можете поставить точку останова на {{тупой биндинг}}, потому что это не JavaScript (или всё-таки?). Чаще всего все закончится закидыванием его в “computed properties” или что-то аналогичное, но теперь ваш JavaScript заполнен дополнительными функциями на объектах, которые не имеют смысла вне фреймворк-специфичного модного вида. А все потому, что ваш фреймворк только наполовину парсит JavaScript выражения для биндингов.
Все очень просто. Программируйте на языке программирования. Не пытайтесь встроить его в ненормальные никогда-не-будущие-стандартом биндинги выдуманные ненадежными JavaScript фреймворками.
Вы наверняка не захотите полностью возвращаться к манипулированию DOM вручную, но ведь есть варианты вроде React (без JSX, поскольку JSX сосет по некоторым причинам описанным выше), который избегает манипуляциями DIM (вместо проповедования идеи описания «текущего положения») и сохраняет весь код как код. Таким образом, все ваши существующие инструменты, минимизаторы и т. д. будут работать отлично. Хотите извлечь функцию чтобы использовать ее еще раз? Без проблем! Хотите переименовать/рефакторить? Без проблем. Хотите использовать TypeScript и иметь поддержку проверки типов в ваших выражениях? Без проблем (TypeScript+React вместе работают лучше).
На работе, один из наших разработчиков строит прототип на React, и я также строю один на Dart (вдохновленный React, генерирующий код элементов, пока я надеюсь, что Dart TagTree превратиться в удобную для использования библиотеку). Ни один из этих прототипов не подвержен тем же проблемам, что эти ужасные {{ глупые биндинги }} в HTML.
HMTL — декларативный язык разметки. Оставьте это так и прекратите пытаться всунуть туда нестандартные биндинги.
Автор:
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/69154
Ссылки в тексте:
[1] TodoMVC: http://todomvc.com/
[2] дерьмо вроде этого: http://stackoverflow.com/a/21492524
[3] Источник: http://habrahabr.ru/post/236045/
Нажмите здесь для печати.