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);
        }
    }

}

  

posted @ 2022-08-11 15:35  飞尽堂前燕  阅读(346)  评论(0编辑  收藏  举报