Межкомпонентная связь с KnockoutJS
Допустим, у вас есть страница обзора продукта со следующими моделями представления:
- ProductIndexViewModel; модель корневого представления, привязанная ко всей странице
- ProductListViewModel; виджет для отображения всех товаров
- ProductRegistrationViewModel; виджет для регистрации новых продуктов
Виджеты загружаются с использованием пользовательских элементов HTML (например, <product-list></product-list>
а также <product-registration></product-registration>
). Это здорово, потому что мне не нужно помещать какие-либо знания об этих виджетах в мою корневую модель. Однако я также хотел бы обновить список продуктов после того, как пользователь зарегистрировал новый продукт. Короче:
Как отправить сигнал из ProductRegistrationViewModel в ProductListViewModel?
Я уже изучил Knockout Postbox, но это, похоже, не решает проблему. Что если у меня есть несколько списков продуктов, и я хочу обновить только один из них? В идеале я хотел бы реализовать ряд открытых методов в модели представления моего компонента. Затем свяжите их вместе из модели корневого представления моей страницы, например так:
var ProductIndexViewModel = function()
{
var productRegistrationComponent = ??;
var productListComponent = ??;
productRegistrationComponent.onRegistrationComplete(function() {
productListComponent.refresh();
};
}
Однако у меня нет доступа к этим моделям представления отсюда. Или я?
Как я могу получить доступ к дочерним моделям представления из моей модели корневого представления?
Наконец, если кто-нибудь увидит лучшее решение моей проблемы: я весь в ушах!
2 ответа
Похоже, они должны делиться наблюдаемым массивом (список продуктов). Я думаю, что было бы лучше определить этот список в корневой модели и передать его виджетам, которые зависят от него. Если оба компонента совместно используют одну и ту же наблюдаемую информацию, вам не нужно беспокоиться о связи между этими двумя компонентами. Ваш HTML может выглядеть примерно так: <product-list data-bind="list: $root.allProducts"></product-list>
,
Как я могу получить доступ к дочерним моделям представления из моей модели корневого представления?
Если вы хотите, вы могли бы использовать ko.contextFor
чтобы получить контекст для элемента HTML.
Я только недавно сделал такого рода вещи. В моем подходе мой компонент создает объект API, который назначается наблюдаемой, которая передается родительским компонентом. Например, у меня есть таблица данных, обернутая компонентом, который я бы хотел найти в выбранных строках:
pageModel = function() {
this.dtAPI = ko.observable();
}
ko.applyBindigns(new pageModel());
<datatable params="api: dtAPI, data: getTableData()"></datatable>
Внутри компонента вы должны установить наблюдаемую ссылку на API для вашего компонента, чтобы другие могли вызывать его вызовы. В моем случае, я не совсем делаю этот случай, я выставляю API для привязки данных, чтобы позже я мог манипулировать элементом привязки данных (в данном случае это связывание с данными:
if (binding.api != null)
{
// expose datatable API to context's api binding.
binding.api({
getSelectedData: function() { return _getSelectedData(element);}
});
}
Затем в основном (родительском) компоненте вы можете сделать что-то вроде:
dtAPI.getSelectedData();
До сих пор я нашел этот шаблон как способ показать поведение из внутреннего компонента полезным.