Разработка

Subscriptions in viewmodel knockout.js

Правильно было бы оставить пару ссылок на предысторию этой статьи, но я обойдусь сухими выжимками кода и вольным переводом частей документации по Knockout.js.

Часто ли вам приходится связывать части своего приложения? Задумываетесь ли вы, насколько сильны эти связи, и что стоит позади тех привычных методов и классов, которые вы используете?

Рассмотрим пример, небольшой, но отражающий суть необходимости событий  и их роли в вашем веб-приложении. Итак, пусть у нас есть список именованых блоков. В каждом блоке есть название и галочка.  Должна быть реализована поддержка “выбрать/снять выделение со всех”, а так же некая возможность изменить весь список.

Описание решения

Я создам две модели для одного блока и для всего приложения в целом. В модели блока будут 2 поля: имя и текущее состояние, а так же подписка на событие ‘поменять значение’. Модель страницы (всего списка) содержит одну галочку для возможности выбрать все, то самое событие будет подпиской на состояние этой галочки. Плюс кнопка, которая обновит список элементов.

Вот моя модель одного элемента. Тут используются две js-библиотеки knockout для двусторонней связи модели и представления и amplify для реализации механизма  событий и подписок.

В коде можно видеть ссылку на константу. Буду оставаться честным, вот объявление внешних констант.

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

В заключение всем хочется видеть разметку 🙂

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

Что выведет это логирование при нажатии на “Select all” при запуске приложения и после изменения списка?

Пока всё логично и верно. Но вот после изменения списка мы увидим следующую картину.

Дальнейшие изменения списка будут только пополнять этот список новыми элементами с номером 4.

Как избежать такого поведения? Что предпринять и как обезопасить своё приложение от ложных действий?

Избежать просто, необходимо следить за всеми подписками, computed переменными и методами вызываемыми через setInterval.

Разработчики knockout позаботились о нас и с введением в 3 версии компонент добавили поддержку метода dispose у модели. К сожалению, для обычной модели и представления, не обёрнутых в компоненты, такого выполнить не удастся, и решением здесь будет только самостоятельный контроль перед удалением.

Вот пример как можно выполнить отписку от событий в нужное для нас время.

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

Исходный код всего примера тут

 

Leave a Reply

Your email address will not be published. Required fields are marked *