Как передавать данные между отдельными компонентами без использования $ scope?
Я составляю компонент, который содержит 3 дочерних компонента таким образом:
Основной компонент содержит список героев. Компонент заголовка содержит две кнопки, которые, как предполагается, должны переключать представление основного компонента на список или представление сетки.
Проблема, с которой я сталкиваюсь сейчас, заключается в передаче данных из компонента header в основной компонент. Поэтому, когда я нажимаю кнопку сетки, вид основного содержимого должен меняться в виде сетки, то же самое для представления строки.
- Как импортировать проекты jQuery в Angular2 TypeScript?
- Угловой материал Не удалось найти основную тему углового материала
- Угловой 2 пользовательских ввода формы
- Как получить параметры запроса от url в угловом 2?
- Угловое 2 с использованием RxJS - принять (1) против первого ()
Как можно передавать данные между дочерними компонентами в угловом 1.5?
- Угловой 2 - Услуги, требующие других услуг до вызова метода
- Как выбрать элемент в шаблоне компонента?
- Выражение ___ изменилось после проверки
- Как обращаться с кодами статуса http, отличными от 200 в Angular 2
- Как установить связь между компонентом в угловом?
- Цепочка RxJS Наблюдаемые данные http в Angular2 с использованием TypeScript
- Как использовать select / option / NgFor для массива объектов в Angular2
- Угловой 2 - возврат данных непосредственно из наблюдаемого
Компонентный подход
Я предлагаю вам согласовать с подходом «Угловой 2» и использовать подход ввода / вывода . Если вы это сделаете, вы сможете легко перейти на Angular 2, потому что компоненты будут концептуально идентичными (с разницей только в синтаксисе). Так вот как вы это делаете.
Поэтому мы хотим, чтобы заголовок и основные компоненты делили часть состояния с заголовком, чтобы изменить его. Есть несколько подходов, которые мы можем использовать, чтобы заставить его работать, но самым простым является использование свойства промежуточного родительского controllerа. Итак, предположим, что родительский controller (или компонент) определяет это свойство view
вы хотите использовать как заголовком (может читать и изменять), так и основными (может читать) компонентами.
Компонент заголовка : вход и выход.
Вот как выглядит простой компонент заголовка:
.component('headerComponent', { template: ` Header component
List Table `, controller: function() { this.setView = function(view) { this.view = view this.onViewChange({$event: {view: view}}) } }, bindings: { view: '<', onViewChange: '&' } })
Наиболее важная часть здесь - привязки. С view: '<'
мы указываем, что компонент header
сможет читать внешнее что-то и связывать его как свойство вида собственного controllerа. С onViewChange: '&'
компоненты определяют выходные данные: канал для уведомления / обновления внешнего мира с тем, что ему нужно. Компонент Header будет вытолкнуть некоторые данные через этот канал, но он не знает, что с ним будет делать родительский компонент, и это не должно волновать.
Таким образом, это означает, что controller header
может использоваться как
Основной компонент : вход.
Основной компонент проще, ему нужно только определить ввод, который он принимает:
.component('mainComponent', { template: ` Main component
Main view: {{ $ctrl.view }} `, bindings: { view: '<' } })
Родительский взгляд
И, наконец, все это связано друг с другом:
Посмотрите и играйте с простой демонстрацией.
angular.module('demo', []) .controller('RootController', function() { this.view = 'table' }) .component('headerComponent', { template: ` Header component
List Table `, controller: function() { this.setView = function(view) { this.view = view this.onViewChange({$event: {view: view}}) } }, bindings: { view: '<', onViewChange: '&' } }) .component('mainComponent', { template: ` Main component
Main view: {{ $ctrl.view }} `, bindings: { view: '<' } })
Root view: {{ root.view }}
Хотя подход с родительским компонентом (передача данных через атрибуты) является идеальной и надежной реализацией, мы можем добиться того же самого более простым способом с использованием фабрики магазинов .
В основном, данные хранятся в Store
, на который ссылаются в области обоих компонентов, что позволяет реагировать на обновления пользовательского интерфейса при изменении состояния.
Пример:
angular .module('YourApp') // declare the "Store" or whatever name that make sense // for you to call it (Model, State, etc.) .factory('Store', () => { // hold a local copy of the state, setting its defaults const state = { data: { heroes: [], viewType: 'grid' } }; // expose basic getter and setter methods return { get() { return state.data; }, set(data) { Object.assign(state.data, data); }, }; });
Затем в ваших компонентах вы должны иметь что-то вроде:
angular .module('YourApp') .component('headerComponent', { // inject the Store dependency controller(Store) { // get the store reference and bind it to the scope: // now, every change made to the store data will // automatically update your component UI this.state = Store.get(); // ... your code }, template: ` ... ... ... ` }) .component('mainComponent', { // same here, we need to inject the Store controller(Store) { // callback for the switch view button this.switchViewType = (type) => { // change the Store data: // no need to notify or anything Store.set({ viewType: type }); }; // ... your code }, template: ` ... `
Если вы хотите увидеть рабочий пример, проверьте этот CodePen .
При этом вы также можете включить связь между 2 или N компонентами . Вам просто нужно:
- вводить зависимость магазина
- убедитесь, что вы привязываете данные хранилища к области вашего компонента
как в примере выше (
).
В реальном мире типичное приложение должно управлять большим количеством данных, поэтому имеет смысл логически разделять области данных каким-то образом. Следуя тому же подходу, вы можете добавить еще магазины . Например, чтобы управлять текущей зарегистрированной информацией пользователя и внешним ресурсом (например, каталогом), вы можете создать UserStore
и CatalogStore
– альтернативно UserModel
и CatalogModel
; эти объекты также будут хорошими местами для централизации таких вещей, как общение с внутренними компонентами, добавление пользовательской бизнес-логики и т . д. Управление данными будет в конечном итоге Store
фабрик Store
.
Имейте в виду, что мы мутируем данные хранилища . Хотя этот подход мертв простым и понятным, он может плохо масштабироваться, потому что он будет давать побочные эффекты . Если вы хотите что-то более продвинутое (неизменность, чистые функции, дерево с одним состоянием и т. Д.), Проверьте Redux или, если вы, наконец, захотите переключиться на Angular 2, посмотрите на ngrx / store .
Надеюсь это поможет! 🙂
Вам не нужно делать это с помощью Angular 2 way, потому что на случай, если вы будете иногда мигрировать … Сделайте это, если это имеет смысл для вас сделать это.
Для достижения этого используйте специальные события. вы можете передавать сообщение через ваше приложение с помощью диспетчеров событий $emit(name, args); or $broadcast(name, args);
$emit(name, args); or $broadcast(name, args);
И вы можете слушать эти события, используя метод $ on (name, listenener);
Надеюсь, поможет
Ссылка: https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit
Пример: вы можете уведомлять об изменениях, как показано ниже, из компонента header
$rootScope.$emit("menu-changed", "list");
И вы можете слушать изменения в директиве основного компонента, например
$rootScope.$on("menu-changed", function(evt, arg){ console.log(arg); });