延續 CSS 筆記 - 使用 ul li 製作互動式下拉選單來延伸做一個信用卡的有效期限選單,本次專案使用 Angular 框架開發,故功能會使用 Angular 的方式記錄。
layout
要呈現的畫面如下圖,
切版內容大致與延續的文章相同,以下就不贅述。
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| <label>信用卡有效期限:</label> <div class="creditCard"> <div class="drop"> <div class="dropOption"> <span>有效月份</span> </div>
<ul class="dropdown"> <li>選項 1</li> <li>選項 2</li> <li>選項 3</li> <li>選項 4</li> <li>選項 5</li> <li>選項 6</li> <li>選項 7</li> <li>選項 8</li> </ul> </div> <span>/</span>
<div class="drop"> <div class="dropOption"> <span>有效年份 </span> </div>
<ul class="dropdown"> <li>選項 1</li> <li>選項 2</li> <li>選項 3</li> <li>選項 4</li> <li>選項 5</li> <li>選項 6</li> <li>選項 7</li> <li>選項 8</li> </ul> </div> </div>
|
SCSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| label { font-size: 24px; padding: 0.5rem; font-weight: bold; color: #333; border-left: orange 5px solid; margin-bottom: 0; } .creditCard { display: flex; align-items: center; padding-top: 1rem; > span { margin: 0 1rem; } .drop { position: relative; display: block; width: 130px; // margin: 0 0 10px; &:hover { .dropOption { display: block; } } &:hover { .dropdown { display: block; } } &:hover { .dropdown.close { display: none; } } .dropOption { position: relative; width: auto; color: #666; font-size: 20px; background-color: #fff; padding: 10px; border: 1px solid #888; border-radius: 5px; box-sizing: border-box; cursor: pointer; &::after { content: ""; position: absolute; top: 20px; right: 12px; border-width: 8px 6px; border-style: solid; border-color: #999 transparent transparent transparent; } } .dropdown { display: none; width: 100%; max-height: 350px; position: absolute; color: #333; padding: 0; margin: 0; background-color: #f9f9f9; box-shadow: 0px 2px 3px 0px #ccc; border-radius: 6px; box-sizing: border-box; overflow: auto; z-index: 10; > li { display: block; color: #000; padding: 12px; font-size: 20px; margin: 0 10px; cursor: pointer; &:first-child { margin: 10px; } &:last-child { margin-bottom: 10px; } &:hover { background-color: #eee; border-radius: 6px; } } &::-webkit-scrollbar { width: 15px; } &::-webkit-scrollbar-track { background-color: #eee; border-radius: 6px; } &::-webkit-scrollbar-thumb { background-color: #888; border-radius: 15px; } &::-webkit-scrollbar-button { background-color: #f9f9f9; } } } }
|
使用 RxJS: range 來完成功能
range
顧名思義就是依照一個範圍內的數列資料建立 Observable
,包含兩個參數:
start
: 從哪個數值開始
count
: 建立多少個數值的數列
簡易範例:
1 2 3 4 5 6 7
| import { range } from "rxjs";
range(3, 4).subscribe((data) => console.log(`range 範例: ${data}`));
|
tip: range 參數只能放 number。
透過以上範例我可以自訂一個數列的範圍,那月份跟年份就有解了,因為都有範圍:
- 月份:1~12 月份,並且我在個位數前面加個 0 ,使資料看起來有一致性。
- 年份:信用卡有效期限基本上在 3 到 5 年左右,所以也不會無限上綱。
想法是我今天只要訂出月份 1 到 12 月,並且建立一個陣列把 1 到 12 月份去模板上跑迴圈,並且使用 click
事件把選到的值重新渲染在畫面上即可。然後我就可以這樣做:
程式碼不長也很簡單。
取得年份與月份
透過 range 建立年份與月份的陣列資料,並透過 click 事件把選到的值渲染在模板上,細節寫在註解中。
app.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| ngOnInit(): void { this.validMonth(); }
creditMonth: string[] = []; monthValue: string;
validMonth() { range(1, 12) .pipe( map((x) => { return ('0' + x.toString()).slice(-2); }) ) .subscribe((res) => { this.creditMonth.push(res); }); }
checkMonth(month: string) { this.monthValue = month; }
|
app.component.html
修改模板語法,加上 ngFor
指令以及 click
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <label>信用卡有效期限:</label> <div class="creditCard"> <div class="drop"> <div class="dropOption"> <span>{{ monthValue ? monthValue : "有效月份" }}</span> </div>
<ul class="dropdown"> <ng-container *ngFor="let item of creditMonth"> <li (click)="checkMonth(item)">{{ item }}</li> </ng-container> </ul> </div> <span>/</span>
<div class="drop"> <div class="dropOption"> <span>{{ yearValue ? yearValue : "有效年份" }} </span> </div>
<ul class="dropdown"> <ng-container *ngFor="let item of creditYear"> <li (click)="checkYear(item)">{{ item }}</li> </ng-container> </ul> </div> </div>
|
小結
善用 RxJS 的 range
事件可以建立有範圍的資料,這次的應用就覺得很有意思,不僅好管理也提升效率,非常推薦喔!
DEMO
連結:https://stackblitz.com/edit/angular-ivy-ppxopm?embed=1&file=src/app/app.component.ts
參考資料