Есть замечательный фреймворк построения веб-приложений — Polymer. Это даже скорее не фреймворк, а реализация идеологии WebComponents в современных реалиях веб-браузеров.
Если кратко, то с его помощью можно реализовывать полноценный, удобный и быстрый (как с точки зрения производительности решения, так и скорости разработки) MVVM в JavaScript:
<dom-module id="my-component"> <template> <h4>ToDo list for {{name}}:</h4> <ul> <template is="dom-repeat" items="{{model.todoitems}}"> <li>{{item.title}}</li> </template> </ul> <button title="ChangeName" on-tap="ChangeName"/> </template> </dom-module> <script> Polymer({ is: 'my-component', name: 'Artur', model: { items: [ {title: '1'} ] }, ChangeName: function() { this.model.name = this.name + "_1"; }, }); </script>
В WPF мы привыкли, что интерфейс перерисовывается автоматически, при изменении значения свойства: this.name = ‘New Name’;. Однако у многих js-mvvm-фреймворков, присвоения приходится производить с помощью магических функций: this.set(‘name’, this.name + «_1»). В Polymer успешно работает первый (удобный :)) вариант, однако при работе с массивами и вложенными объектами эти прелести заканчиваются. Код добавления новых элементов в список ToDo выглядит примерно так:
Add: function() { this.push('items', {title: 'another item'}); }
Редактирование же элементов в списке (например, изменение title) будет еще более ужасным:
this.set('items.1.title', 'new title!');
Конечно от этого хочется избавится (и не только мне :)). Для этого и был создан компонент dom-bind-notifier. К сожалению, с актуальными версиями Polymer у него проблемы, и для этого его пришлось немного пропатчить, результат доступен у меня на github (также можно установить через bower install dom-bind-notifier-polymerpatch). Использование в сценарии выше крайне просто: добавляем тег
<button title="ChangeName" on-tap="ChangeName"/> <dom-bind-notifier observed-object="{{model}}" path="model" deep></dom-bind-notifier> </template>
После этого старые-добрые присвоения отлично работают:
Add: function() { this.model.items.push({title: 'another item'}); }, Change: function() { this.model.items[1].title = 'another item'; }
Функционирует подписываясь на браузерный Object.Observe.
Полный пример использования — по ссылке. Не стесняйтесь сделать View Source :)
Успешного использования!
Так ведь от Object.observe в blink решено избавиться, в edge добавлять тоже не планируют. http://caniuse.com/#search=Object.observe
Согласен. Собственно, здесь и написано об использовании полифиллов на данный момент.
В будущем подобное можно будет реализовать через Proxy, который вроде бы приняли.
Polymer — это всего лишь небольшая обёртка над стандартными веб-компонентами. С чего её будут забрасывать? Скорее уж Ангуляр потихоньку будет терять популярность ввиду перехода всё большего количества разработчиков на нативную реализацию того же функционала, что предоставляет Ангуляр — точно так же, как её продолжает понемногу терять jQuery.