mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(grid-list): avoid recreating tile coordinator for every change detection (#13226)
Currently we recreate the `TileCoordinator` and throw out the old one on every change detection run. These changes reuse a single `TileCoordinator` and update it instead, which ends up shaving off a couple of milliseconds off each layout and reduces the amount of objects that need to be garbage collected. **Note:** this is a breaking API change for the `TileCoordinator`, however it isn't exported through `material/grid-list`.
This commit is contained in:
committed by
Jeremy Elbourn
parent
0ac41a0896
commit
18f46cfbbd
@@ -47,6 +47,9 @@ export class MatGridList implements OnInit, AfterContentChecked {
|
||||
/** Number of columns being rendered. */
|
||||
private _cols: number;
|
||||
|
||||
/** Used for determiningthe position of each tile in the grid. */
|
||||
private _tileCoordinator: TileCoordinator;
|
||||
|
||||
/**
|
||||
* Row height value passed in by user. This can be one of three types:
|
||||
* - Number value (ex: "100px"): sets a fixed row height to that value
|
||||
@@ -135,8 +138,14 @@ export class MatGridList implements OnInit, AfterContentChecked {
|
||||
|
||||
/** Computes and applies the size and position for all children grid tiles. */
|
||||
private _layoutTiles(): void {
|
||||
const tracker = new TileCoordinator(this.cols, this._tiles);
|
||||
if (!this._tileCoordinator) {
|
||||
this._tileCoordinator = new TileCoordinator(this._tiles);
|
||||
}
|
||||
|
||||
const tracker = this._tileCoordinator;
|
||||
const direction = this._dir ? this._dir.value : 'ltr';
|
||||
|
||||
this._tileCoordinator.update(this.cols);
|
||||
this._tileStyler.init(this.gutterSize, tracker, this.cols, direction);
|
||||
|
||||
this._tiles.forEach((tile, index) => {
|
||||
|
||||
@@ -44,7 +44,7 @@ export class TileCoordinator {
|
||||
* Ex: A list with 1 row that contains a tile with rowspan 2 will have a total rowspan of 2.
|
||||
*/
|
||||
get rowspan() {
|
||||
let lastRowMax = Math.max(...this.tracker);
|
||||
const lastRowMax = Math.max(...this.tracker);
|
||||
// if any of the tiles has a rowspan that pushes it beyond the total row count,
|
||||
// add the difference to the rowcount
|
||||
return lastRowMax > 1 ? this.rowCount + lastRowMax - 1 : this.rowCount;
|
||||
@@ -53,17 +53,25 @@ export class TileCoordinator {
|
||||
/** The computed (row, col) position of each tile (the output). */
|
||||
positions: TilePosition[];
|
||||
|
||||
constructor(numColumns: number, tiles: QueryList<MatGridTile>) {
|
||||
constructor(private _tiles: QueryList<MatGridTile>) {}
|
||||
|
||||
/**
|
||||
* Updates the tile positions.
|
||||
* @param numColumns Amount of columns in the grid.
|
||||
*/
|
||||
update(numColumns: number) {
|
||||
this.columnIndex = 0;
|
||||
this.rowIndex = 0;
|
||||
|
||||
this.tracker = new Array(numColumns);
|
||||
this.tracker.fill(0, 0, this.tracker.length);
|
||||
|
||||
this.positions = tiles.map(tile => this._trackTile(tile));
|
||||
this.positions = this._tiles.map(tile => this._trackTile(tile));
|
||||
}
|
||||
|
||||
/** Calculates the row and col position of a tile. */
|
||||
private _trackTile(tile: MatGridTile): TilePosition {
|
||||
// Find a gap large enough for this tile.
|
||||
let gapStartIndex = this._findMatchingGap(tile.colspan);
|
||||
const gapStartIndex = this._findMatchingGap(tile.colspan);
|
||||
|
||||
// Place tile in the resulting gap.
|
||||
this._markTilePosition(gapStartIndex, tile);
|
||||
|
||||
Reference in New Issue
Block a user