ng-select大量数据导致卡顿问题修复 二次简易封装
html部分
<div class="sd-select">
<nz-select #select [nzMode]="nzMode|| 'default'" [(ngModel)]="value" [nzAllowClear]="nzAllowClear || true"
[nzPlaceHolder]="nzPlaceHolder || ''" (nzOpenChange)="updateCouponList($event)" [nzServerSearch]="true"
[nzShowSearch]="(nzShowSearch && !disabled) || false" (ngModelChange)="handleOnChange($event)"
(nzOnSearch)="onSearch($event)" [nzDisabled]="disabled" (nzScrollToBottom)="scrollToBottom()">
<nz-option *ngFor="let option of showOptions" [nzLabel]="!!optionLabel? option[optionLabel]: option"
[nzValue]="!!optionValue?option[optionValue]: option">
</nz-option>
</nz-select>
</div>
ts部分
import { isArray } from '@common/is-type';
import { Component, OnInit, Input, forwardRef, OnChanges, SimpleChanges, ViewChild } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { NzSelectComponent } from 'ng-zorro-antd';
@Component({
selector: 'sd-select',
styleUrls: ['./select.component.less'],
templateUrl: './select.component.html',
preserveWhitespaces: false,
providers: [{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => SelectComponent)
}]
})
export class SelectComponent implements OnInit, ControlValueAccessor, OnChanges {
@Input() nzMode: 'multiple' | 'default';
@Input() nzAllowClear?: boolean;
@Input() nzShowSearch?: boolean;
@Input() nzPlaceHolder?: string;
@Input() options: Array<any>;
@Input() optionLabel: string;
@Input() optionValue: string;
@Input() pageSize: number = 20;
@ViewChild('select') selectComponent: NzSelectComponent;
value = null;
pageNum = 0;
showOptions = [];
inputValue = [];
disabled = false;
nzOptionContainerComponent: any;
onChange: (value: string | string[]) => void = () => null;
onTouched: () => void = () => null;
constructor(
) { }
handleOnChange($event) {
this.onChange($event);
}
ngOnChanges(changes): void {
if (changes.options && changes.options.currentValue.length > 0) {
this.renderShowOptions(this.value);
}
}
getSelectList(value) {
if (isArray(value)) {
return this.options.filter(item => value.indexOf(item[this.optionValue]) !== -1)
} else {
return this.options.filter(item => item[this.optionValue] === value);
}
}
renderShowOptions(value) {
let options = [];
if (this.optionLabel) {
options = this.getSelectList(value);
} else {
options = isArray(value) ? value : [value];
}
this.showOptions = options;
}
// 封装组件搭配form的formControlName 使用
writeValue(value: any): void {
this.value = value;
if (value) {
this.renderShowOptions(value);
}
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState(disabled: boolean) {
this.disabled = disabled;
}
ngOnInit() {
setTimeout(() => {
/**
* 复写 dropDownScroll 方法 用于解决部分浏览器滚动到底部计算问题
* 注意:此方法只适用于 ng-zorro1.8版本,8.0版本以上ng-zorro已经修复此bug
* 源码位置: ng-zorro-antd\esm5\select\nz-option-container.component.js
* NzOptionContainerComponent.prototype.dropDownScroll = function(e, ul){};
*/
this.selectComponent.nzOptionContainerComponent.dropDownScroll = function (e, ul) {
e.preventDefault();
e.stopPropagation();
if (ul && (ul.scrollHeight - ul.scrollTop <= ul.clientHeight + 50)) {
this.nzScrollToBottom.emit();
}
};
}, 500);
}
onSearch(str) {
if (!str) return;
let labelName = this.optionLabel || null;
this.showOptions = this.options.filter(item => {
if (labelName) {
return (item[labelName] + '').indexOf(str) !== -1
} else {
return (item + '').indexOf(str) !== -1;
}
});
}
scrollToBottom() {
console.log('scroll to bottom =====>', this.pageNum, this.options.length, this.pageSize);
if (this.pageNum > Math.ceil(this.options.length / this.pageSize)) return;
this.pageNum++;
this.showOptions = [...this.options.slice(0, this.pageNum * this.pageSize + this.pageSize)];
}
updateCouponList(state) {
console.log('show open change ======================>', state);
if (state) {
this.pageNum = 0;
this.showOptions = this.options.slice(0, this.pageSize);
} else {
setTimeout(() => {
this.showOptions = [];
}, 500);
}
}
}