# 实现思路

1. 月份只有十二个，只要把个位数做好补位就好
2. 年份的生成是可控的(传参)，当前年份往前推几年和往后推几年构成；
3. 数据遍历结构很简单
{
date:2017, // 月份是字符串，年份是数字
active:false,
type:'year' // 月份是'month'
}复制代码

# 实现代码

• html
<div class="only-year-month-select">
<div class="select" (click)="isExpand = !isExpand">
<input type="text" [placeholder]="placeholder" class="form-control" [(ngModel)]="selected" [disabled]="true">
</div>
<div class="sub-list1">
<p class="title">年份</p>
<ul class="year-wrap">
<li *ngFor="let i of selectYearRange;let index = index" [class.active]="i.active" (click)="actValue(selectYearRange,index)"
(dblclick)="emitResult(i)">{{i.date}}</li>
</ul>
</div>
<div class="sub-list2">
<p class="title">月份</p>
<ul class="month-wrap">
<li *ngFor="let i of selectMonthRange;let index = index" [class.active]="i.active" (click)="actValue(selectMonthRange,index)"
(dblclick)="emitResult(i)">{{i.date}}</li>
</ul>
</div>
</div>
</div>复制代码
• components
import { Component, OnInit, Input, Output, EventEmitter, HostListener, ElementRef } from '@angular/core';

// 动画

@Component({
selector: 'app-only-year-month-select',
templateUrl: './only-year-month-select.component.html',
styleUrls: ['./only-year-month-select.component.scss'],
})
export class OnlyYearMonthSelectComponent implements OnInit {
@Input() public placeholder: string;
@Input() public range: any;
@Output() public result = new EventEmitter();
public isExpand = false;
public selectYear: any;
public selectMonth: any;
public selectYearRange: Array<any> = [];
public selectMonthRange: Array<any> = [];
public selected: any;
constructor(
private _el: ElementRef
) { }

ngOnInit() {
this.getCurrentDate();
}

// 获取当前的年月
getCurrentDate(): void {
const TODAY = new Date();
this.selectYear = TODAY.getFullYear();
this.selectMonth = TODAY.getMonth() < 9 ? '0' + (TODAY.getMonth() + 1) : String(TODAY.getMonth() + 1);
this.selectYearRange.push(
{
date: this.selectYear,
active: true,
type: 'year'
}
);
this.selectMonthRange.push(
{
date: this.selectMonth,
active: true,
type: 'month'
}
);
this.selectYearRange = this.getRangeYear(this.selectYear, this.range.before, this.range.after);
this.selectMonthRange = this.getRangeMonth(this.selectMonth);
console.log(this.selectYearRange, this.selectMonthRange);
}

// 需要生成的日期范围
getRangeYear(year: number, before: number = 5, after: number = 10): any {
// console.log(year, before, after);

let _beforeYear = year;
let _afterYear = year;

for (let i = 0; i < before; i++) {
this.selectYearRange.unshift(
{
date: --_beforeYear,
active: false,
type: 'year'
}
);
}
for (let j = 0; j < after; j++) {
this.selectYearRange.push(
{
date: ++_afterYear,
active: false,
type: 'year'
}
);
}
return this.selectYearRange;
}

// 月份范围
getRangeMonth(month): any {
for (let i = 0; i < 12; i++) {
const temp = i < 9 ? '0' + (i + 1) : '' + (i + 1);
if (month !== temp) {
this.selectMonthRange.push(
{
date: temp,
active: false,
type: 'month'
});
}
}
this.selectMonthRange.sort(this.compare('date'));
return this.selectMonthRange;
}

// 数组对象排序
compare(property) {
return function (a, b) {
const value1 = a[property];
const value2 = b[property];
return value1 - value2;
};
}

// 年份或者月份选择
actValue(list: any, index: number) {

list.forEach((v, i) => {
if (i === index) {
v.active = true;
if (v.type === 'year') {
console.log(v.date);
this.selectYear = v.date;
}
if (v.type === 'month') {
console.log(v.date);
this.selectMonth = v.date;
}

} else {
v.active = false;
}
});
this.emitResult();
}

// 获取结果集
emitResult(e?: any) {
if (e) { // 双击则关闭弹出
this.isExpand = false;
}
this.selected = this.selectYear + '-' + this.selectMonth;
this.result.emit(this.selected);

}

// 监听全局点击事件
@HostListener('document:click', ['\$event.target'])
public onClick(targetElement) {
const clickedInside = this._el.nativeElement.contains(targetElement);
if (!clickedInside) {
this.isExpand = false;
this.emitResult();
}

}
}复制代码
// 动画的效果很简单，就是把css3的效果用js来实现，具体的效果就是渐现
// 放在突然出来一块区域的地方，触发看起来会比较顺眼，有个过渡

import { trigger, state, style, transition, animate, keyframes } from '@angular/animations';
//transition(':enter', [ ... ]); // void => *
//transition(':leave', [ ... ]); // * => void
state('in', style({ display: 'none' })),
transition('void => *', [
animate(200, keyframes([
style({ height: '0', opacity: 0, offset: 0 }),
style({ height: '*', opacity: 1, offset: 1 })
]))
]),
transition('* => void', [
animate(200, keyframes([
style({ height: '*', opacity: 1, offset: 0 }),
style({ height: '0', opacity: 0, offset: 1 })
]))
]),
]);

// 200 是过渡时间，毫秒
// offset相当于 css3 中keyframes的百分比，，控制动画的进度的。。0 -> 1 就相当于 0% -> 100%复制代码
• 封装成一个模块给其他使用
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

import { OnlyYearMonthSelectComponent } from './only-year-month-select.component';

@NgModule({
imports: [
CommonModule, // 用用到一些内置的指令必须依赖这个，比如*ngIF, *ngFor
FormsModule // 有用到表单元素必须引入这货
],
declarations: [OnlyYearMonthSelectComponent], // 声明年月组件
exports: [OnlyYearMonthSelectComponent] // 导出年月组件
})
export class OnlyYearMonthSelectModule { }复制代码

# 组件使用

• 若不是以模块的方式到处，只要在使用的模块引入组件声明下就能使用
• 反之则需要引入这个模块，方可使用

• module
// 在要使用的模块中引入
// 公用组件
import { MitEhartsModule } from '../../../widgets/mit-echarts/mit-echarts.module';
import { MitDataTableModule } from '../../../widgets/mit-data-table/mit-data-table.module';
import { OnlyYearMonthSelectModule } from '../../../share/only-year-month-select/only-year-month-select.module';
import { DepartmentSelectModule } from '../../../share/department-select/department-select.module';
const mitModule = [
MitEhartsModule,
MitDataTableModule,
DepartmentSelectModule,
OnlyYearMonthSelectModule
]
@NgModule({
imports: [
CommonModule,
FormsModule,
NgbDatepickerModule,
...mitModule,
DailyCarRoutes
],
providers: [DailyCarService],
declarations: [...page]
}复制代码
• html
<div class="form-group condition-wrapper">
<label class="form-control-label">月份</label>
<app-only-year-month-select class="form-control" [placeholder]="'yyyy-mm'" (result)="Time = \$event" [range]="{before:5,after:10}"></app-only-year-month-select>
</div>复制代码

# 总结

0 条评论

## 相关文章

3838

3259

2023

3796

4086

### MobX 在 React Native开发中的应用

MobX 是一款精准的状态管理工具库，如果你在 React 和 React Native 应用中使用过 Flux、Alt、Redux 和 Reflux，那毫不犹...

5278

2722

2533

1022

1271