Вы разрушили HTML

в 11:18, , рубрики: AngularJS, backbone, ember, html, javascript, javascript framework, knockoutjs, Веб-разработка

Если вы кого-нибудь спросите, на чем он делает клиентскую сторону своих приложений сегодня, этот человек наверняка ответит, что использует какой-нибудь хипстерский JS-фреймворк, вроде Angular, Ember, Knockout, Backbone или Polymer (смотрите сайт TodoMVC).

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

<!-- 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 }}, но скоро окажется, что ваши выражения вырастают в сложный бардак. Вы поймете, что встроенная функциональность — не совсем то, что вам нужно и начнете гнуть свой фреймворк под дерьмо вроде этого, используя функцию 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 — декларативный язык разметки. Оставьте это так и прекратите пытаться всунуть туда нестандартные биндинги.

Автор:

Источник

* - обязательные к заполнению поля