Angular共享组件配置私有@ngrx/store:依赖与初始化方案问询
Hey there! Let's break this down step by step to get your Angular 5 shared component using NgRx internally—without exposing it to consuming apps, even if those apps have their own NgRx setup.
1. Component-Side Configuration (Package & Module Setup)
Package.json Dependencies
The goal is to keep NgRx entirely internal to your component, so:
- Add
@ngrx/storetodependencies(notpeerDependencies). This ensures the package is installed automatically when consuming apps add your component, but they don't need to explicitly manage or know about it. Use a version compatible with Angular 5 (NgRx 4.x is the right match here). - Keep only Angular core packages in
peerDependencies—these are required for the component to work, and consuming apps will already have them installed.
Example snippet:
{ "name": "your-shared-component", "version": "1.0.0", "dependencies": { "@angular/core": "^5.2.0", "@angular/common": "^5.2.0", "@ngrx/store": "^4.1.0" }, "peerDependencies": { "@angular/core": "^5.0.0 || ^6.0.0", "@angular/common": "^5.0.0 || ^6.0.0" } }
Component Module Initialization (my-component.module.ts)
To isolate NgRx from the consuming app, create a standalone, internal store for your component instead of using the global NgRx module setup (which would conflict with the app's store if it exists).
- Define your component's reducer and state (e.g.,
component.reducer.ts):
export interface ComponentState { isLoading: boolean; data: any[]; } export const initialState: ComponentState = { isLoading: false, data: [] }; export function componentReducer(state = initialState, action: any): ComponentState { switch (action.type) { case 'LOAD_DATA': return { ...state, isLoading: true }; case 'LOAD_DATA_SUCCESS': return { ...state, isLoading: false, data: action.payload }; default: return state; } }
- Create an internal store service (e.g.,
component-store.service.ts) to hold your component's isolated NgRx store:
import { Injectable } from '@angular/core'; import { createStore, Store } from '@ngrx/store'; import { ComponentState, componentReducer, initialState } from './component.reducer'; @Injectable({ providedIn: 'root' }) export class ComponentStoreService { readonly store: Store<ComponentState>; constructor() { // Create a standalone store instance exclusively for your component this.store = createStore(componentReducer, initialState); } }
- Configure your component module:
Declare your component and provide internal services, but don't expose any NgRx-related code to the outside:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { YourSharedComponent } from './your-shared.component'; import { ComponentStoreService } from './component-store.service'; @NgModule({ imports: [CommonModule], declarations: [YourSharedComponent], exports: [YourSharedComponent], // Only export the component itself providers: [ComponentStoreService] // Skip if you used `providedIn: 'root'` }) export class MyComponentModule { }
2. Consuming App Configuration
Package.json Dependencies
- Only install your shared component package. You don't need to add
@ngrx/storeunless the app wants to use its own independent NgRx setup.
Example snippet:
{ "dependencies": { "@angular/core": "^5.2.0", "@angular/common": "^5.2.0", "your-shared-component": "^1.0.0", // Optional: Add your app's own NgRx if needed "@ngrx/store": "^4.1.0" } }
App Module Initialization (app.module.ts)
Import your component module and use the component directly—no NgRx setup is required for the component itself. If the app uses its own NgRx, it will operate independently of your component's internal store.
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import { MyComponentModule } from 'your-shared-component'; // Optional: Import your app's own NgRx setup import { StoreModule } from '@ngrx/store'; import { appReducer } from './app.reducer'; @NgModule({ imports: [ BrowserModule, MyComponentModule, // Add your shared component module // Optional: Setup the app's independent NgRx store StoreModule.forRoot({ appState: appReducer }) ], declarations: [AppComponent], bootstrap: [AppComponent] }) export class AppModule { }
You can now use the component in any template without worrying about NgRx:
<app-your-shared-component></app-your-shared-component>
内容的提问来源于stack exchange,提问作者Lyn Headley

