ionic 示例工程(一) —— 封裝並使用 ionic 列表元件
阿新 • • 發佈:2020-12-30
目錄
一.封裝基本列表元件
ths-list.component.html
<!-- 下拉重新整理 --> <!--<ion-refresher *ngIf="update" slot="fixed" (ionRefresh)="updateData($event)">--> <!-- <ion-refresher-content pullingIcon="chevron-down" refreshingSpinner="circles">--> <!-- </ion-refresher-content>--> <!--</ion-refresher>--> <ion-list> <!-- 遍歷 dataList, 生成列表每一項 --> <!-- [detail]="type === 'detail'": 行尾顯示箭頭 'detail' 為顯示箭頭,預設顯示,'favorite' 為不顯示 --> <!-- (click)="openDetail(item)":點選後開啟詳情頁 --> <ion-item *ngFor="let item of dataList" [detail]="type === 'detail'" (click)="openDetail(item)" > <!-- 頭像放在開始的位置, 如果存在 預設icon 或者 item 中含有 iconField 屬性, 就會顯示頭像 --> <ion-avatar slot="start" *ngIf="icon || item[iconField]"> <!-- iconField 優先順序高於 icon --> <ion-img [src]="item[iconField] ? item[iconField] : icon"></ion-img> </ion-avatar> <!-- 列表標題 和 列表描述資訊 --> <ion-label> <!-- 列表標題 會顯示 列表項中的 titleField 屬性, 或者 -- --> <h3 class="title">{{ item[titleField] || "--" }}</h3> <!-- 列表描述資訊 , 被整合成一個 row整體, 裡面三行 --> <ion-row> <!-- [class.half-width]="desType === 'double'": 詳情顯示的樣式, 預設為 single --> <!-- single: 一行顯示一個詳情; double: 一行顯示兩個詳情 --> <!-- 遍歷描述列表, showAlias: 是否顯示中文描述, 只有傳入字串'true'時, 顯示中文描述 --> <span class="description" [class.half-width]="desType === 'double'" *ngFor="let des of desMapper"> {{ (showAlias === "true" ? des + ":" : "") + item[des] }} </span> </ion-row> </ion-label> </ion-item> </ion-list> <!-- 上拉載入更多 --> <!--<ion-infinite-scroll *ngIf="loadMore" (ionInfinite)="loadMoreData($event)">--> <!-- <ion-infinite-scroll-content loadingSpinner="circles" loadingText="資料載入中...">--> <!-- </ion-infinite-scroll-content>--> <!--</ion-infinite-scroll>-->
ths-list.component.ts
/** * 列表元件基本邏輯 */ export class ThsListComponent implements OnInit, DoCheck, OnChanges { /** * 上拉載入更多的滾動 */ @ViewChild(IonInfiniteScroll, { static: false }) infiniteScroll: IonInfiniteScroll; // 列表項資料列表,是個物件組成的陣列 public dataList: Array<object>; // 列表項的描述資訊,是個字串組成的陣列 public desMapper: Array<string>; /** * 輸入資料 */ // 列表資料 @Input() data: Array<object>; // 要在首行顯示的欄位名 @Input() titleField: string; // 欄位別名(用於在列表中顯示中文的描述名稱,如:姓名:XXX 中的 姓名,同時有排序的功能) @Input() aliasFields: object; // 顯示中文描述, 預設顯示 @Input() showAlias: string; // 左側顯示的圖示 @Input() icon: string; // 優先順序更高的 左側顯示的圖示 @Input() iconField: string; // detail:行尾顯示箭頭,預設 detail,favorite 表示不顯示箭頭 @Input() type: "detail" | "favorite" | null = "detail"; // 列表項對應的詳情頁地址 @Input() detailUrl: string; // 描述資訊顯示格式:single 一行顯示一個 double 一行顯示兩個,預設為 single @Input() desType: "single" | "double" | null = "single"; /** * 傳出資料 */ // 每個列表項的點選事件 @Output() itemClick = new EventEmitter<object>(); // 下拉重新整理的事件 @Output() update = new EventEmitter<object>(); // 上拉載入更多的事件 @Output() loadMore = new EventEmitter<object>(); // 檢測不同, 檢測變化 private differ: any; constructor(private router: Router, private differs: KeyValueDiffers) { this.differ = differs.find([]).create(); } ngDoCheck() { if (this.differ.diff(this.data)) { this.dataList = (this.data || []).map((item) => { if (this.aliasFields) { const mapped = Object.keys(item).map((key) => { const newKey = this.aliasFields[key] || key; return { [newKey]: item[key] }; }); return Object.assign({}, ...mapped); } else { return item; } }); } } ngOnChanges(changes) { // 如果詳情頁展示的 欄位名 發生變化 if (changes.aliasFields) { // 儲存描述資訊的陣列 就等於 詳情頁展示的欄位名所構成的陣列的鍵名 所構成的陣列 this.desMapper = Object.keys(this.aliasFields || {}).map( (key) => this.aliasFields[key] );} } /** * 下拉重新整理 */ updateData(event) { this.infiniteScroll.disabled = false; this.update.emit(event); } /** * 上拉載入 */ loadMoreData(event) { this.loadMore.emit(event); } /** * 跳轉到詳情頁 */ openDetail(item: object) { if (this.detailUrl) { // 跳轉到該列表項的詳情頁, 並把該列表項傳給下一個頁面 this.router.navigate([this.detailUrl], { queryParams: item }); } this.itemClick.emit(item); } ngOnInit(): void {} }
二.封裝列表詳細資訊頁元件
list.detail.page.html
<ion-header> <ion-toolbar color="primary"> <ion-title> {{data.title}} </ion-title> <ion-buttons slot="start"> <ion-back-button text=""></ion-back-button> </ion-buttons> </ion-toolbar> </ion-header> <ion-content> <ion-list> <!-- 遍歷鍵值列表 --> <ion-item *ngFor="let key of keyList"> <!-- 排除渲染鍵值列表中的 icon選項 和 title選項 --> <ion-label *ngIf="key !== 'icon' && key !== 'title'"> {{key}}: {{data[key]}} </ion-label> <!-- 如果鍵值中有 icon選項, 就把他作為圖片地址進行渲染 --> <ion-img [src]="data[key]" *ngIf="key === 'icon'"></ion-img> </ion-item> </ion-list> </ion-content>
list.detail.page.ts
export class ListDetailPage implements OnInit { // 從上級頁面獲取的列表項資料 public data: any; // 列表項資料的鍵值列表 public keyList: string[]; constructor(private activatedRoute: ActivatedRoute) { } ngOnInit(): void { this.activatedRoute.queryParams.subscribe(data => { // 獲取路由引數 this.data = data; // 獲取路由引數物件中的鍵值列表 this.keyList = Object.keys(this.data); // 把陣列的第一個元素刪除 this.keyList.shift(); }); } }
三.在目標專案頁面中,使用封裝好的元件(主要看這裡)
3.1 封裝好的元件使用步驟
- 將上面一中封裝好的基本列表元件ths-list ,拷貝到目標專案的 components 資料夾中
- 在需要使用該元件的頁面的 module.ts 檔案中,引入 ThsListModule 模組,並在 import 中宣告
import { ThsListModule } from '../../../../components/ths-list/ths-list.module';
`- 在需要使用該元件的頁面的html 檔案中,使用對應標籤
- <app-ths-list></app-ths-list>
3.2 引數說明
- 【必填】data: {[propName: string]: string}[]:
- 傳入的資料列表,與引數 titleField、aliasFields、iconField 一起進行欄位展示,資料列表中物件的欄位名,必須與這三個引數相匹配
> data = "[ > { > title: '小明', > icon: 'https://ionicframework.com/docs/demos/api/list/avatar-luke.png', > tel: '13888888888', > age: '24', > sex: '男', > }, ... > ]";
- 【必填】titleField: string:
- 要在首行顯示的欄位名,比如:titleField = "title",上面就是把 小明 當成首行顯示的欄位名
- 如果寫成這樣子:titleField="2333",會顯示右下效果
- 【選填】aliasFields: {[propName: string]: string}:
- 要在詳情展示的欄位名的集合,與 itemClick() 事件 和 引數 showAlias 一起使用
aliasFields = "{ sex: 'sex', age: '年齡', tel: 'tel', }";
- 將 sex,age,tel 這三個屬性作為詳情進行展示,('性別', '年齡', '電話') 作為中文描述在 itemClick() 事件 和 引數 showAlias 中使用
- 【選填】iconField: string:
- 左側展示圖片的路徑存放的欄位名,優先順序高於 引數 icon,比如:iconField = "icon",上面將 icon 屬性的值,作為圖片路徑
- 【選填】icon: string:
- 左側顯示的圖示,比如:icon = "https://ionicframework.com/docs/demos/api/list/avatar-yoda.png"
- 【選填】showAlias: string:
- 是否顯示中文描述,傳入值為 'true' 時,顯示中文描述,比如:showAlias = "true",會將描述中的 sex 改為 性別,就是換成中文了
- 【選填】type: 'detail' | 'favorite' | null = 'detail':
- 行尾是否顯示箭頭,'detail' 為顯示箭頭,預設顯示,'favorite' 為不顯示,比如:
type = 'favorite'
表示行尾不顯示箭頭- 【選填】detailUrl: string:
- 點選跳轉的頁面地址,會把當前列表項 item 的資訊帶入下一頁面
- 【選填】desType: 'single' | 'double' | null = 'single':
- 詳情佈局顯示的方式,single 表示一行顯示一個詳情,double 表示一行顯示兩個詳情,預設為 single
- 【選填】itemClick = new EventEmitter<object>():
- 每個列表項的點選事件,比如:
(itemClick)="openDetail($event)"
,$event 為當前列表項 item 的資訊- 每個列表項 item 打印出來的效果是這樣的:
3.3 使用封裝元件示例
- 示例一:帶不同頭像的列表
- 示例二:帶相同頭像的列表,因為 icon="/assets/img/wolf.png" 所以有相同頭像
- 示例三:示例3:無頭像雙列列表,因為 desType="double" 所以兩列顯示
list.page.html
<!-- 示例1:帶不同頭像的列表 --> <ths-list // 資料列表 [data]="dataList1" // 要在首行顯示的欄位名 titleField="title" // 詳情展示欄位名列表 [aliasFields]="aliasFields1" // 左側顯示的頭像 iconField="icon" // 是否將 詳情頁欄位名 顯示為 中文 showAlias="true" // 每個資料項的 描述資訊的 展示方式 desType="single" // 定義在列表基礎元件中封裝的事件 itemClick (itemClick)="openDetail($event)"> </ths-list> <!-- 示例2:帶相同頭像的列表,因為 icon="/assets/img/wolf.png" 所以有相同頭像 --> <ths-list [data]="dataList2" titleField="title" [aliasFields]="aliasFields2" icon="/assets/img/wolf.png" showAlias="false" (itemClick)="openDetail($event)"></ths-list> <!-- 示例3:無頭像雙列列表,因為 desType="double" 所以兩列顯示 --> <ths-list [data]="dataList2" titleField="title" [aliasFields]="aliasFields2" desType="double" type="detail" (itemClick)="openDetail($event)"></ths-list>
list.page.ts
// 資料列表1 public dataList1: {[propName: string]: string}[]; // 詳情展示列表1 public aliasFields1: {[propName: string]: string}; // 資料列表2 / 資料列表3 public dataList2: {[propName: string]: string}[]; // 詳情展示列表2 / 詳情展示列表3 public aliasFields2: {[propName: string]: string}; constructor(private router: Router) { } ngOnInit(): void { /** * 示例1 資料 */ this.aliasFields1 = { // 資料列表每一項的詳情 sex: 'sex', age: 'age', tel: 'tel', }; this.dataList1 = [ // 資料列表項 { title: '小明', icon: '/assets/img/xiaoming.png', tel: '13888888888', age: '24', sex: '男', }, ... ]; /** * 示例2 / 示例3 資料 */ this.aliasFields2 = { // 資料列表每一項的詳情 role: '角色', msg: '資訊', }; this.dataList2 = [ // 資料列表項 { title: '小明', role: '平民', msg: '夜晚只能睡覺' }, ... ]; /** * 開啟詳情事件 * 該方法接受列表項本身作為一個物件,並作為路由引數進行傳遞 */ openDetail(item: any): void { this.router.navigate(['/list-detail'], {queryParams: item}); } }