angular5 通過服務實現數據的傳遞
中間人模式的限制是必須有共同的父組件,在實戰中搜索組件和商品列表組件沒有共同的父組件(搜索組件的父組件是app, 而商品列表的組件的父組件是Home組件,所以兩者沒有共同的組件), 所以他們只能使用服務來實現傳遞。
父子組件的數據傳遞使用屬性傳值,而兄弟組件的數據傳遞是使用中間人模式。而兩者之間沒有直接關系則是用服務(兩者共同的依賴)來聯系。
1. 項目需求(搜索組件和商品組件) a. 搜索組件(通過單擊搜索按鈕,來實現右側的商品組件的顯示結果, 是一個響應的表單)b. 商品列表組件(是一個單獨的組件,顯示商品的列表)
2. 本次叠代的需求,當在搜索組件中填寫相關的內容,然後單擊"搜索"按鈕,然後在商品的列表的組件中顯示符合你選擇的條件的商品,當都不選擇時, 顯示所有的 商品列表。
搜索組件和產品組件擁有共同的服務,服務的文件的名稱為:product.service.ts,在這個組件中,要實現的是:
在這個服務的文件中首先要實現的功能是:
一,在服務中,含有向服務器發送http請求的函數
1 search(params: ProductSearchParams): Observable<Product[]> { 2 return this.http.get(‘/apa/products‘, {search: this.encodeParams(params)}).map((res) => res.json());3 } 4 5 private encodeParams(params: ProductSearchParams) { 6 let result: URLSearchParams; 7 result = Object.keys(params) 8 .filter(key => params[key]) 9 .reduce((sum:URLSearchParams, key:string) => { 10 sum.append(key, params[key]);11 return sum; 12 }, new URLSearchParams()); 13 return result; 14 }
1 export class ProductSearchParams { 2 constructor( 3 public title: string, 4 public price: number, 5 public category: string 6 ){ 7 8 } 9 }
註解:這個服務中的search函數的參數是響應式表單返回的對象(第二個代碼是搜索的對象的數據格式), 返回的數據的格式是流,他的泛型是Product的數組,返回的是通過http實現的流。encodeParams的函數的返回的是search的參數,數據的傳遞是通過url地址傳參的格式,實現url的參數的組合。
二,
1 searchEvent: EventEmitter<ProductSearchParams> = new EventEmitter();
在product.service.ts中定義了發射器,EventEmitter既可以實現數據的發射也可以實現數據的接收。在這個文件中實現事件發射是因為使搜索組件和商品組件實現解耦合。
三,在搜索組件中給搜索按鈕添加click事件,通過響應式表單實現,此時要註意的是key值的統一,即表單的字段的key和搜索表單的formControlName的名字key值要一樣,在這個文件中,不把EventEmitter添加到這個文件中的作用是實現搜索組件和商品組件的解耦:
1 onSubmit() { 2 const valid: boolean = this.formModel.valid; 3 if (valid) { 4 console.log(this.formModel.value); 5 this.productService.searchEvent.emit(this.formModel.value); // 事件的發射 6 } 7 }
四,在商品的組件中實現對搜索組件發射的流的訂閱:
1 ngOnInit() { 2 // 首次登陸的時候對商品的展示 3 this.productService.getProducts() 4 .subscribe(data => { 5 this.products = data; 6 }); 7 // 通過搜索按鈕實現的發射的流的接收和訂閱 8 this.productService.searchEvent.subscribe( 9 params => this.productService.search(params).subscribe(data => this.products = data) 10 ) 11 }
在上述的函數中,實現了對搜索組件中搜索按鈕觸發的單擊事件的訂閱,在訂閱的函數中,通過獲取了事件流的數據,即搜索的參數,在發射事件的訂閱函數中實現對
獲取http的流的觸發,即訂閱服務中的search事件函數,通過subscribe來觸發從服務器中獲取數據。
註: 1. 在獲取的products數組展示在模板中,由於是從服務器中獲取的數據,是異步的操作,所以存在頁面的展示的時候,後端的數據仍然沒有返回的時候,所以在模板上使用(?.)的格式來展示數據,而*ngFor指令則不需這麽做,是因為它自己有自己的判斷空值的操作,所以不會報錯。
五,Node服務器的設置的代碼的編寫:
1 app.get(‘/apa/products‘,function(req, res) { 2 var result = products; 3 var params = req.query; 4 console.log(params); 5 if (params.title) { 6 result = result.filter(function(p) { 7 return p.title.indexOf(params.title) != -1; 8 }) 9 } 10 11 if (params.price && result.length > 0) { 12 result = result.filter(function(p) { 13 return p.price <= params.price; 14 }) 15 } 16 17 if (params.category && params.category != ‘-1‘ && result.length > 0) { 18 result = result.filter(function(p) { 19 console.log(p.categories); 20 console.log(params.category); 21 return p.categories.indexOf(params.category) != -1; 22 }) 23 } 24 25 res.json(result); 26 })
本文中最重要的是通過服務來傳送和訂閱來實現數據的傳遞。將事件的觸發和接收訂閱都放在服務中,而使搜索組件和商品組件的解耦,而這是組件的編寫的核心思想。
angular5 通過服務實現數據的傳遞