Angular:在更改属性之前等待模板完成渲染

时间:2021-03-18 15:25:30

标签: javascript css angular typescript

我正在开发一个小型图库组件,它通过 @Input() 将元素作为数组接收。元素本身包含文本或图像:

打字稿

// [...]
export class SlidesComponent implements OnInit, AfterViewInit {

    // currently displayed item index
    private _currentItemIndex = 0;

    // Width of an item, in this case as wide as the mask (see below)
    itemWidth = 0;

    // Slides
    @Input() slides: SlideInterface[] = [];

    // UL which will contain the LIs
    @ViewChild( 'ul', { read: ElementRef } ) ul!: ElementRef;

    // Mask around the UL
    @ViewChild( 'mask', { read: ElementRef } ) mask!: ElementRef;



    constructor() {}

    ngOnInit(): void {
         // [ ... ]
    }

    ngAfterViewInit(): void {
        // Detect Mask size
        this.itemWidth = this.mask.nativeElement.getBoundingClientRect().width;
    }

    // set scrollLeft-Value in template
    get listLeft(): number {
        return this.itemWidth * this._currentItemIndex;
    }

    // [ ... ]
}

模板

在模板中,元素在 LI 元素内的 *ngFor 循环中创建为 UL 标签。在此过程中,我会显示文本或图像。

<div class="slides-mask" #mask [scrollLeft]="listLeft">
    <ul class="slides" #ul [style.width]="itemWidth * slides.length + 'px'">
        <li *ngFor="let item of items"
            class="slide"
            [style.width]="itemWidth + 'px'">

            <ng-container [ngSwitch]="item.type">
                <!-- Text -->
                <div class="slide-content html-content"
                     [innerHTML]="item.content"
                     *ngSwitchCase="'html'"></div>

                <!-- Image -->
                <my-image *ngSwitchCase="'image'"
                           [src]="item.content.image.src"></my-image>

                <!-- more to come ... -->
            </ng-container>

        </li>
    </ul>
</div>

样式

每个LI元素与封闭掩码一样宽,其余LI元素排列在水平轴的UL中。使用这种方法滚动和滑动手指非常容易,CSS 代码使用 scroll-behaviorscroll-snap-typescroll-snap-align 处理大部分。

.slides-mask {
    width: 100%;
    height: 100%;
    overflow-x: scroll;
    overflow-y: hidden;
    scroll-behavior: smooth;
    scroll-snap-type: x mandatory;
}
.slides {
    display: flex;
    height: 100%;
    flex-flow: row nowrap;
    justify-content: space-between;
    width: auto;
}
.slide {
    scroll-snap-align: start;
}

到目前为止,一切正常。

问题

如果我想从例如开始第三个元素,我可以通过更改属性 [scrollLeft] 在掩码上使用 _currentItemIndex 指定所需的位置。

但这仅在我将 _currentItemIndex 的更改延迟几百毫秒时才有效,这很难看

另一种方法

为了检查浏览器窗口内的任何大小变化,我添加了一个如下所示的 ResizeObserver。获取大小工作正常,但仍然没有显示所需的幻灯片。

// ...
ngAfterViewInit(): void {
    // ...
    const r = new ResizeObserver( ( items: any[] ) => {
            this.itemWidth = items[ 0 ].contentRect.width;
            // Jump to Slide 2
            this._currentItemIndex = 1; // <-- this is not working
        });
        r.observe( this.mask.nativeElement );
}
// ...

所以

当模板中的所有元素渲染完成后,我该如何采取行动?

0 个答案:

没有答案