1e41f4b71Sopenharmony_ci# Reducing Redundant Operations on First Frame Drawing 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci------ 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci## Application Cold Start and Home Page Loading and Drawing 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciA code start is a startup mode where an application is started from scratch – the background does not have a process of the application, and therefore the system creates a new process and allocates it to the application. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ciThe cold start process can be divided into four phases: application process creation and initialization, application and ability initialization, ability lifecycle, and home page loading and drawing, as shown below. 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ciHome page loading and drawing is not only one of the four phases of application cold start, but also the most important phase of first frame drawing. It can be further divided into three phases: page load, measurement and layout, and render. This topic explores how application performance can be improved at these phases. 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ci## Reducing Page Load Time 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ciYou can reduce your page load time by loading pages on demand or reducing the lifecycle time of custom components. 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ci#### On-demand Loading 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ciOn-demand loading, as its name implies, loads resources only when they are needed. It avoids initializing and loading all elements at a time. In this way, the time required for creating list elements is reduced, allowing pages to load faster. 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ci**Negative example**: There is a list with 10,000 elements (the sheer number is intended to make it easier to observe the benefits of on-demand loading). If each of the list element is initialized and loaded during page load, the page load time will be excessively long. 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ci```ts 28e41f4b71Sopenharmony_ci@Entry 29e41f4b71Sopenharmony_ci@Component 30e41f4b71Sopenharmony_cistruct AllLoad { 31e41f4b71Sopenharmony_ci @State arr: String[] = Array.from(Array<string>(10000), (val,i) =>i.toString()); 32e41f4b71Sopenharmony_ci build() { 33e41f4b71Sopenharmony_ci List() { 34e41f4b71Sopenharmony_ci ForEach(this.arr, (item: string) => { 35e41f4b71Sopenharmony_ci ListItem() { 36e41f4b71Sopenharmony_ci Text(`item value: ${item}`) 37e41f4b71Sopenharmony_ci .fontSize(20) 38e41f4b71Sopenharmony_ci .margin({ left: 10 }) 39e41f4b71Sopenharmony_ci } 40e41f4b71Sopenharmony_ci }, (item: string) => item.toString()) 41e41f4b71Sopenharmony_ci } 42e41f4b71Sopenharmony_ci } 43e41f4b71Sopenharmony_ci} 44e41f4b71Sopenharmony_ci``` 45e41f4b71Sopenharmony_ci 46e41f4b71Sopenharmony_ci**Optimization**: Replace **ForEach** with **LazyForEach** to avoid initializing and loading all elements at a time. 47e41f4b71Sopenharmony_ci 48e41f4b71Sopenharmony_ci```ts 49e41f4b71Sopenharmony_ciclass BasicDataSource implements IDataSource { 50e41f4b71Sopenharmony_ci private listeners: DataChangeListener[] = []; 51e41f4b71Sopenharmony_ci private originDataArray: string[] = []; 52e41f4b71Sopenharmony_ci 53e41f4b71Sopenharmony_ci public totalCount(): number { 54e41f4b71Sopenharmony_ci return 0; 55e41f4b71Sopenharmony_ci } 56e41f4b71Sopenharmony_ci 57e41f4b71Sopenharmony_ci public getData(index: number): string { 58e41f4b71Sopenharmony_ci return this.originDataArray[index] 59e41f4b71Sopenharmony_ci } 60e41f4b71Sopenharmony_ci 61e41f4b71Sopenharmony_ci // Register a listener for data changes. 62e41f4b71Sopenharmony_ci registerDataChangeListener(listener: DataChangeListener): void { 63e41f4b71Sopenharmony_ci if (this.listeners.indexOf(listener) < 0) { 64e41f4b71Sopenharmony_ci console.info('add listener') 65e41f4b71Sopenharmony_ci this.listeners.push(listener) 66e41f4b71Sopenharmony_ci } 67e41f4b71Sopenharmony_ci } 68e41f4b71Sopenharmony_ci 69e41f4b71Sopenharmony_ci // Deregister the listener for data changes. 70e41f4b71Sopenharmony_ci unregisterDataChangeListener(listener: DataChangeListener): void { 71e41f4b71Sopenharmony_ci const pos = this.listeners.indexOf(listener); 72e41f4b71Sopenharmony_ci if (pos >= 0) { 73e41f4b71Sopenharmony_ci console.info('remove listener') 74e41f4b71Sopenharmony_ci this.listeners.splice(pos, 1) 75e41f4b71Sopenharmony_ci } 76e41f4b71Sopenharmony_ci } 77e41f4b71Sopenharmony_ci 78e41f4b71Sopenharmony_ci // Invoked when all data is reloaded. 79e41f4b71Sopenharmony_ci notifyDataReload(): void { 80e41f4b71Sopenharmony_ci this.listeners.forEach(listener => { 81e41f4b71Sopenharmony_ci listener.onDataReloaded() 82e41f4b71Sopenharmony_ci }) 83e41f4b71Sopenharmony_ci } 84e41f4b71Sopenharmony_ci 85e41f4b71Sopenharmony_ci // Invoked when data is added to the position indicated by the specified index. 86e41f4b71Sopenharmony_ci notifyDataAdd(index: number): void { 87e41f4b71Sopenharmony_ci this.listeners.forEach(listener => { 88e41f4b71Sopenharmony_ci listener.onDataAdd(index) 89e41f4b71Sopenharmony_ci }) 90e41f4b71Sopenharmony_ci } 91e41f4b71Sopenharmony_ci 92e41f4b71Sopenharmony_ci // Invoked when data in the position indicated by the specified index is changed. 93e41f4b71Sopenharmony_ci notifyDataChange(index: number): void { 94e41f4b71Sopenharmony_ci this.listeners.forEach(listener => { 95e41f4b71Sopenharmony_ci listener.onDataChange(index) 96e41f4b71Sopenharmony_ci }) 97e41f4b71Sopenharmony_ci } 98e41f4b71Sopenharmony_ci 99e41f4b71Sopenharmony_ci // Invoked when data is deleted from the position indicated by the specified index. LazyForEach will update the displayed content accordingly. 100e41f4b71Sopenharmony_ci notifyDataDelete(index: number): void { 101e41f4b71Sopenharmony_ci this.listeners.forEach(listener => { 102e41f4b71Sopenharmony_ci listener.onDataDelete(index) 103e41f4b71Sopenharmony_ci }) 104e41f4b71Sopenharmony_ci } 105e41f4b71Sopenharmony_ci 106e41f4b71Sopenharmony_ci // Invoked when data is moved. 107e41f4b71Sopenharmony_ci notifyDataMove(from: number, to: number): void { 108e41f4b71Sopenharmony_ci this.listeners.forEach(listener => { 109e41f4b71Sopenharmony_ci listener.onDataMove(from, to) 110e41f4b71Sopenharmony_ci }) 111e41f4b71Sopenharmony_ci } 112e41f4b71Sopenharmony_ci} 113e41f4b71Sopenharmony_ci 114e41f4b71Sopenharmony_ciclass MyDataSource extends BasicDataSource { 115e41f4b71Sopenharmony_ci private dataArray: string[] = Array.from(Array<string>(10000), (val, i) => i.toString()); 116e41f4b71Sopenharmony_ci 117e41f4b71Sopenharmony_ci public totalCount(): number { 118e41f4b71Sopenharmony_ci return this.dataArray.length 119e41f4b71Sopenharmony_ci } 120e41f4b71Sopenharmony_ci 121e41f4b71Sopenharmony_ci public getData(index: number): string { 122e41f4b71Sopenharmony_ci return this.dataArray[index] 123e41f4b71Sopenharmony_ci } 124e41f4b71Sopenharmony_ci 125e41f4b71Sopenharmony_ci public addData(index: number, data: string): void { 126e41f4b71Sopenharmony_ci this.dataArray.splice(index, 0, data) 127e41f4b71Sopenharmony_ci this.notifyDataAdd(index) 128e41f4b71Sopenharmony_ci } 129e41f4b71Sopenharmony_ci 130e41f4b71Sopenharmony_ci public pushData(data: string): void { 131e41f4b71Sopenharmony_ci this.dataArray.push(data) 132e41f4b71Sopenharmony_ci this.notifyDataAdd(this.dataArray.length - 1) 133e41f4b71Sopenharmony_ci } 134e41f4b71Sopenharmony_ci} 135e41f4b71Sopenharmony_ci 136e41f4b71Sopenharmony_ci@Entry 137e41f4b71Sopenharmony_ci@Component 138e41f4b71Sopenharmony_cistruct SmartLoad { 139e41f4b71Sopenharmony_ci private data: MyDataSource = new MyDataSource() 140e41f4b71Sopenharmony_ci 141e41f4b71Sopenharmony_ci build() { 142e41f4b71Sopenharmony_ci List() { 143e41f4b71Sopenharmony_ci LazyForEach(this.data, (item: string) => { 144e41f4b71Sopenharmony_ci ListItem() { 145e41f4b71Sopenharmony_ci Text(`item value: ${item}`) 146e41f4b71Sopenharmony_ci .fontSize(20) 147e41f4b71Sopenharmony_ci .margin({ left: 10 }) 148e41f4b71Sopenharmony_ci } 149e41f4b71Sopenharmony_ci }, (item:string) => item) 150e41f4b71Sopenharmony_ci } 151e41f4b71Sopenharmony_ci } 152e41f4b71Sopenharmony_ci} 153e41f4b71Sopenharmony_ci``` 154e41f4b71Sopenharmony_ci 155e41f4b71Sopenharmony_ci 156e41f4b71Sopenharmony_ci 157e41f4b71Sopenharmony_ci#### Reducing Lifecycle of Custom Components 158e41f4b71Sopenharmony_ci 159e41f4b71Sopenharmony_ciThe custom component lifecycle **aboutToAppear** is time-consuming and, if not well managed, may greatly increase page load times and even block subsequent layout rendering of the main thread. Therefore, the lifecycle needs to be converted to a worker thread task so that the page can be rendered without waiting for the lifecycle to be completed first and the main thread will not be blocked at the startWindowIcon page. 160e41f4b71Sopenharmony_ci 161e41f4b71Sopenharmony_ci**Negative example**: The time-consuming lifecycle of a custom component blocks the layout rendering of the main thread. 162e41f4b71Sopenharmony_ci 163e41f4b71Sopenharmony_ci```ts 164e41f4b71Sopenharmony_ci@Entry 165e41f4b71Sopenharmony_ci@Component 166e41f4b71Sopenharmony_cistruct TaskSync { 167e41f4b71Sopenharmony_ci @State private text: string = ""; 168e41f4b71Sopenharmony_ci private count: number = 0; 169e41f4b71Sopenharmony_ci 170e41f4b71Sopenharmony_ci aboutToAppear() { 171e41f4b71Sopenharmony_ci this.text = 'hello world'; 172e41f4b71Sopenharmony_ci this.computeTask(); // Synchronization task 173e41f4b71Sopenharmony_ci } 174e41f4b71Sopenharmony_ci 175e41f4b71Sopenharmony_ci build() { 176e41f4b71Sopenharmony_ci Column({space: 10}) { 177e41f4b71Sopenharmony_ci Text(this.text).fontSize(50) 178e41f4b71Sopenharmony_ci } 179e41f4b71Sopenharmony_ci .width('100%') 180e41f4b71Sopenharmony_ci .height('100%') 181e41f4b71Sopenharmony_ci .padding(10) 182e41f4b71Sopenharmony_ci } 183e41f4b71Sopenharmony_ci 184e41f4b71Sopenharmony_ci computeTask() { 185e41f4b71Sopenharmony_ci this.count = 0; 186e41f4b71Sopenharmony_ci while (this.count < 100000000) { 187e41f4b71Sopenharmony_ci this.count++; 188e41f4b71Sopenharmony_ci } 189e41f4b71Sopenharmony_ci this.text = 'task complete'; 190e41f4b71Sopenharmony_ci } 191e41f4b71Sopenharmony_ci} 192e41f4b71Sopenharmony_ci``` 193e41f4b71Sopenharmony_ci 194e41f4b71Sopenharmony_ci**Optimization**: Convert the time-consuming lifecycle to a worker thread task. In this way, the page is drawn first, and then the worker thread result is sent to the main thread and updated to the page. 195e41f4b71Sopenharmony_ci 196e41f4b71Sopenharmony_ci```ts 197e41f4b71Sopenharmony_ci// TaskAsync.ets 198e41f4b71Sopenharmony_ciimport worker from '@ohos.worker'; 199e41f4b71Sopenharmony_ci 200e41f4b71Sopenharmony_ci@Entry 201e41f4b71Sopenharmony_ci@Component 202e41f4b71Sopenharmony_cistruct TaskAsync { 203e41f4b71Sopenharmony_ci @State private text: string = ""; 204e41f4b71Sopenharmony_ci private workerInstance:worker.ThreadWorker = new worker.ThreadWorker("entry/ets/workers/worker.ts"); 205e41f4b71Sopenharmony_ci 206e41f4b71Sopenharmony_ci aboutToAppear() { 207e41f4b71Sopenharmony_ci // Process messages from the worker thread. 208e41f4b71Sopenharmony_ci this.workerInstance.onmessage = (message)=> { 209e41f4b71Sopenharmony_ci console.info('message from worker: ' + JSON.stringify(message)) 210e41f4b71Sopenharmony_ci this.text = JSON.parse(JSON.stringify(message)).data 211e41f4b71Sopenharmony_ci this.workerInstance.terminate() 212e41f4b71Sopenharmony_ci } 213e41f4b71Sopenharmony_ci this.text = 'hello world'; 214e41f4b71Sopenharmony_ci // Execute the worker thread task. 215e41f4b71Sopenharmony_ci this.computeTaskAsync(); 216e41f4b71Sopenharmony_ci } 217e41f4b71Sopenharmony_ci 218e41f4b71Sopenharmony_ci build() { 219e41f4b71Sopenharmony_ci Column({space: 10}) { 220e41f4b71Sopenharmony_ci Text(this.text).fontSize(50) 221e41f4b71Sopenharmony_ci } 222e41f4b71Sopenharmony_ci .width('100%') 223e41f4b71Sopenharmony_ci .height('100%') 224e41f4b71Sopenharmony_ci .padding(10) 225e41f4b71Sopenharmony_ci } 226e41f4b71Sopenharmony_ci private async computeTaskAsync(){ 227e41f4b71Sopenharmony_ci // Send a message to the worker thread. 228e41f4b71Sopenharmony_ci this.workerInstance.postMessage('hello world') 229e41f4b71Sopenharmony_ci } 230e41f4b71Sopenharmony_ci} 231e41f4b71Sopenharmony_ci``` 232e41f4b71Sopenharmony_ci 233e41f4b71Sopenharmony_ci```ts 234e41f4b71Sopenharmony_ci// worker.ts 235e41f4b71Sopenharmony_ciimport worker from '@ohos.worker'; 236e41f4b71Sopenharmony_ci 237e41f4b71Sopenharmony_cilet parentPort = worker.workerPort; 238e41f4b71Sopenharmony_ci 239e41f4b71Sopenharmony_cifunction computeTask(count: number) { 240e41f4b71Sopenharmony_ci while (count < 100000000) { 241e41f4b71Sopenharmony_ci count++; 242e41f4b71Sopenharmony_ci } 243e41f4b71Sopenharmony_ci return 'task complete' 244e41f4b71Sopenharmony_ci} 245e41f4b71Sopenharmony_ci// Process messages from the main thread. 246e41f4b71Sopenharmony_ciparentPort.onmessage = (message) => { 247e41f4b71Sopenharmony_ci console.info("onmessage: " + JSON.stringify(message)); 248e41f4b71Sopenharmony_ci // Send a message to the main thread. 249e41f4b71Sopenharmony_ci parentPort.postMessage(computeTask(0)); 250e41f4b71Sopenharmony_ci} 251e41f4b71Sopenharmony_ci``` 252e41f4b71Sopenharmony_ci 253e41f4b71Sopenharmony_ci 254e41f4b71Sopenharmony_ci 255e41f4b71Sopenharmony_ci## Reducing Layout Time 256e41f4b71Sopenharmony_ci 257e41f4b71Sopenharmony_ciReducing layout time can be achieved by asynchronous loading and reduced nesting. 258e41f4b71Sopenharmony_ci 259e41f4b71Sopenharmony_ci#### Asynchronous Loading 260e41f4b71Sopenharmony_ci 261e41f4b71Sopenharmony_ciDuring synchronous loading, images are loaded in the main thread. This means that, page layout needs to wait until the main thread has completed the **makePixelMap** task, resulting in long page layout times. On the contrary, during asynchronous loading, images are loaded in other threads while page layout is executed in the main thread. In this way, no blocking occurs, leading to faster page layout and better performance. However, not all image loading must be asynchronous loading. For small local images that are fast to load, synchronous loading (with **syncLoad** set to **true**) is preferrable. 262e41f4b71Sopenharmony_ci 263e41f4b71Sopenharmony_ci**Negative example**: The **\<Image>** component is used to synchronously load high-resolution images, blocking the UI thread and increasing the total page layout time. 264e41f4b71Sopenharmony_ci 265e41f4b71Sopenharmony_ci```ts 266e41f4b71Sopenharmony_ci@Entry 267e41f4b71Sopenharmony_ci@Component 268e41f4b71Sopenharmony_cistruct SyncLoadImage { 269e41f4b71Sopenharmony_ci @State arr: String[] = Array.from(Array<string>(100), (val,i) =>i.toString()); 270e41f4b71Sopenharmony_ci build() { 271e41f4b71Sopenharmony_ci Column() { 272e41f4b71Sopenharmony_ci Row() { 273e41f4b71Sopenharmony_ci List() { 274e41f4b71Sopenharmony_ci ForEach(this.arr, (item: string) => { 275e41f4b71Sopenharmony_ci ListItem() { 276e41f4b71Sopenharmony_ci Image($r('app.media.4k')) 277e41f4b71Sopenharmony_ci .border({ width: 1 }) 278e41f4b71Sopenharmony_ci .borderStyle(BorderStyle.Dashed) 279e41f4b71Sopenharmony_ci .height(100) 280e41f4b71Sopenharmony_ci .width(100) 281e41f4b71Sopenharmony_ci .syncLoad(true) 282e41f4b71Sopenharmony_ci } 283e41f4b71Sopenharmony_ci }, (item: string) => item.toString()) 284e41f4b71Sopenharmony_ci } 285e41f4b71Sopenharmony_ci } 286e41f4b71Sopenharmony_ci } 287e41f4b71Sopenharmony_ci } 288e41f4b71Sopenharmony_ci} 289e41f4b71Sopenharmony_ci``` 290e41f4b71Sopenharmony_ci 291e41f4b71Sopenharmony_ci**Optimization**: The **\<Image>** component is loaded in the default asynchronous loading mode, which avoids blocking the UI thread and reduces the page layout time. 292e41f4b71Sopenharmony_ci 293e41f4b71Sopenharmony_ci```ts 294e41f4b71Sopenharmony_ci@Entry 295e41f4b71Sopenharmony_ci@Component 296e41f4b71Sopenharmony_cistruct AsyncLoadImage { 297e41f4b71Sopenharmony_ci @State arr: String[] = Array.from(Array<string>(100), (val,i) =>i.toString()); 298e41f4b71Sopenharmony_ci build() { 299e41f4b71Sopenharmony_ci Column() { 300e41f4b71Sopenharmony_ci Row() { 301e41f4b71Sopenharmony_ci List() { 302e41f4b71Sopenharmony_ci ForEach(this.arr, (item: string) => { 303e41f4b71Sopenharmony_ci ListItem() { 304e41f4b71Sopenharmony_ci Image($r('app.media.4k')) 305e41f4b71Sopenharmony_ci .border({ width: 1 }) 306e41f4b71Sopenharmony_ci .borderStyle(BorderStyle.Dashed) 307e41f4b71Sopenharmony_ci .height(100) 308e41f4b71Sopenharmony_ci .width(100) 309e41f4b71Sopenharmony_ci } 310e41f4b71Sopenharmony_ci }, (item: string) => item.toString()) 311e41f4b71Sopenharmony_ci } 312e41f4b71Sopenharmony_ci } 313e41f4b71Sopenharmony_ci } 314e41f4b71Sopenharmony_ci } 315e41f4b71Sopenharmony_ci} 316e41f4b71Sopenharmony_ci``` 317e41f4b71Sopenharmony_ci 318e41f4b71Sopenharmony_ci 319e41f4b71Sopenharmony_ci 320e41f4b71Sopenharmony_ci#### Reducing Nesting 321e41f4b71Sopenharmony_ci 322e41f4b71Sopenharmony_ciThe view hierarchy can significantly affect application performance. Flatter view hierarchies can bring faster page layout and better layout performance. Therefore, whenever possible, reduce nesting and eliminate misplaced container components. 323e41f4b71Sopenharmony_ci 324e41f4b71Sopenharmony_ci**Negative example**: A **\<Grid>** container is used to load 1000 grids at a time, and additional three-layer **\<Flex>** containers are used , resulting in an unnecessarily deeply nested structure. 325e41f4b71Sopenharmony_ci 326e41f4b71Sopenharmony_ci```ts 327e41f4b71Sopenharmony_ci@Entry 328e41f4b71Sopenharmony_ci@Component 329e41f4b71Sopenharmony_cistruct Depth1 { 330e41f4b71Sopenharmony_ci @State number: Number[] = Array.from(Array<number>(1000), (val, i) => i); 331e41f4b71Sopenharmony_ci scroller: Scroller = new Scroller() 332e41f4b71Sopenharmony_ci 333e41f4b71Sopenharmony_ci build() { 334e41f4b71Sopenharmony_ci Column() { 335e41f4b71Sopenharmony_ci Grid(this.scroller) { 336e41f4b71Sopenharmony_ci ForEach(this.number, (item: number) => { 337e41f4b71Sopenharmony_ci GridItem() { 338e41f4b71Sopenharmony_ci Flex() { 339e41f4b71Sopenharmony_ci Flex() { 340e41f4b71Sopenharmony_ci Flex() { 341e41f4b71Sopenharmony_ci Text(item.toString()) 342e41f4b71Sopenharmony_ci .fontSize(16) 343e41f4b71Sopenharmony_ci .backgroundColor(0xF9CF93) 344e41f4b71Sopenharmony_ci .width('100%') 345e41f4b71Sopenharmony_ci .height(80) 346e41f4b71Sopenharmony_ci .textAlign(TextAlign.Center) 347e41f4b71Sopenharmony_ci .border({width:1}) 348e41f4b71Sopenharmony_ci } 349e41f4b71Sopenharmony_ci } 350e41f4b71Sopenharmony_ci } 351e41f4b71Sopenharmony_ci } 352e41f4b71Sopenharmony_ci }, (item:string) => item) 353e41f4b71Sopenharmony_ci } 354e41f4b71Sopenharmony_ci .columnsTemplate('1fr 1fr 1fr 1fr 1fr') 355e41f4b71Sopenharmony_ci .columnsGap(0) 356e41f4b71Sopenharmony_ci .rowsGap(0) 357e41f4b71Sopenharmony_ci .size({ width: "100%", height: "100%" }) 358e41f4b71Sopenharmony_ci } 359e41f4b71Sopenharmony_ci } 360e41f4b71Sopenharmony_ci} 361e41f4b71Sopenharmony_ci``` 362e41f4b71Sopenharmony_ci 363e41f4b71Sopenharmony_ci**Optimization**: A **\<Grid>** container is used to load 1000 grids at a time, but this time no unnecessary containers are used, which leads to faster layout. 364e41f4b71Sopenharmony_ci 365e41f4b71Sopenharmony_ci```ts 366e41f4b71Sopenharmony_ci@Entry 367e41f4b71Sopenharmony_ci@Component 368e41f4b71Sopenharmony_cistruct Depth2 { 369e41f4b71Sopenharmony_ci @State number: Number[] = Array.from(Array<number>(1000), (val, i) => i); 370e41f4b71Sopenharmony_ci scroller: Scroller = new Scroller() 371e41f4b71Sopenharmony_ci 372e41f4b71Sopenharmony_ci build() { 373e41f4b71Sopenharmony_ci Column() { 374e41f4b71Sopenharmony_ci Grid(this.scroller) { 375e41f4b71Sopenharmony_ci ForEach(this.number, (item: number) => { 376e41f4b71Sopenharmony_ci GridItem() { 377e41f4b71Sopenharmony_ci Text(item.toString()) 378e41f4b71Sopenharmony_ci .fontSize(16) 379e41f4b71Sopenharmony_ci .backgroundColor(0xF9CF93) 380e41f4b71Sopenharmony_ci .width('100%') 381e41f4b71Sopenharmony_ci .height(80) 382e41f4b71Sopenharmony_ci .textAlign(TextAlign.Center) 383e41f4b71Sopenharmony_ci .border({width:1}) 384e41f4b71Sopenharmony_ci } 385e41f4b71Sopenharmony_ci }, (item:string) => item) 386e41f4b71Sopenharmony_ci } 387e41f4b71Sopenharmony_ci .columnsTemplate('1fr 1fr 1fr 1fr 1fr') 388e41f4b71Sopenharmony_ci .columnsGap(0) 389e41f4b71Sopenharmony_ci .rowsGap(0) 390e41f4b71Sopenharmony_ci .size({ width: "100%", height: "100%" }) 391e41f4b71Sopenharmony_ci } 392e41f4b71Sopenharmony_ci } 393e41f4b71Sopenharmony_ci} 394e41f4b71Sopenharmony_ci``` 395e41f4b71Sopenharmony_ci 396e41f4b71Sopenharmony_ci 397e41f4b71Sopenharmony_ci 398e41f4b71Sopenharmony_ci## Reducing Render Time 399e41f4b71Sopenharmony_ci 400e41f4b71Sopenharmony_ciYou can reduce render time by replacing visibility control with conditional rendering. 401e41f4b71Sopenharmony_ci 402e41f4b71Sopenharmony_ci#### Conditional Rendering 403e41f4b71Sopenharmony_ci 404e41f4b71Sopenharmony_ciReplacing visibility control with conditional rendering can significantly reduce the render time during first frame drawing. With visibility control, even if a component is hidden, it still needs to be re-created when the page is re-rendered. Therefore, in scenarios where performance is critical, you are advised to use conditional rendering instead. 405e41f4b71Sopenharmony_ci 406e41f4b71Sopenharmony_ci**Negative example**: The **visibility** attribute is used to display or hide the component. 407e41f4b71Sopenharmony_ci 408e41f4b71Sopenharmony_ci```ts 409e41f4b71Sopenharmony_ci@Entry 410e41f4b71Sopenharmony_ci@Component 411e41f4b71Sopenharmony_cistruct VisibilityExample { 412e41f4b71Sopenharmony_ci build() { 413e41f4b71Sopenharmony_ci Column() { 414e41f4b71Sopenharmony_ci Column() { 415e41f4b71Sopenharmony_ci // The component is hidden and does not take up space in the layout. 416e41f4b71Sopenharmony_ci Text('None').fontSize(9).width('90%').fontColor(0xCCCCCC) 417e41f4b71Sopenharmony_ci Row().visibility(Visibility.None).width('90%').height(80).backgroundColor(0xAFEEEE) 418e41f4b71Sopenharmony_ci 419e41f4b71Sopenharmony_ci // The component is hidden but takes up space in the layout. 420e41f4b71Sopenharmony_ci Text('Hidden').fontSize(9).width('90%').fontColor(0xCCCCCC) 421e41f4b71Sopenharmony_ci Row().visibility(Visibility.Hidden).width('90%').height(80).backgroundColor(0xAFEEEE) 422e41f4b71Sopenharmony_ci 423e41f4b71Sopenharmony_ci // The component is visible, which is the default display mode. 424e41f4b71Sopenharmony_ci Text('Visible').fontSize(9).width('90%').fontColor(0xCCCCCC) 425e41f4b71Sopenharmony_ci Row().visibility(Visibility.Visible).width('90%').height(80).backgroundColor(0xAFEEEE) 426e41f4b71Sopenharmony_ci }.width('90%').border({ width: 1 }) 427e41f4b71Sopenharmony_ci }.width('100%').margin({ top: 5 }) 428e41f4b71Sopenharmony_ci } 429e41f4b71Sopenharmony_ci} 430e41f4b71Sopenharmony_ci``` 431e41f4b71Sopenharmony_ci 432e41f4b71Sopenharmony_ci**Optimization**: Conditional rendering is used to replace visibility control. 433e41f4b71Sopenharmony_ci 434e41f4b71Sopenharmony_ci```ts 435e41f4b71Sopenharmony_ci@Entry 436e41f4b71Sopenharmony_ci@Component 437e41f4b71Sopenharmony_cistruct IsVisibleExample { 438e41f4b71Sopenharmony_ci @State isVisible : boolean = true; 439e41f4b71Sopenharmony_ci 440e41f4b71Sopenharmony_ci build() { 441e41f4b71Sopenharmony_ci Column(){ 442e41f4b71Sopenharmony_ci Column() { 443e41f4b71Sopenharmony_ci // The component is not rendered. In this way, it is hidden and does not take up space in the layout. 444e41f4b71Sopenharmony_ci Text('None').fontSize(9).width('90%').fontColor(0xCCCCCC) 445e41f4b71Sopenharmony_ci if (!this.isVisible) { 446e41f4b71Sopenharmony_ci Row().width('90%').height(80).backgroundColor(0xAFEEEE) 447e41f4b71Sopenharmony_ci } 448e41f4b71Sopenharmony_ci 449e41f4b71Sopenharmony_ci // Conditional rendering cannot be used to hide the component with it still taking up space in the layout. 450e41f4b71Sopenharmony_ci 451e41f4b71Sopenharmony_ci // The component is rendered. In this way, it becomes visible. 452e41f4b71Sopenharmony_ci Text('Visible').fontSize(9).width('90%').fontColor(0xCCCCCC) 453e41f4b71Sopenharmony_ci if (this.isVisible){ 454e41f4b71Sopenharmony_ci Row().width('90%').height(80).backgroundColor(0xAFEEEE) 455e41f4b71Sopenharmony_ci } 456e41f4b71Sopenharmony_ci }.width('90%').border({ width: 1 }) 457e41f4b71Sopenharmony_ci }.width('100%').margin({ top: 5 }) 458e41f4b71Sopenharmony_ci } 459e41f4b71Sopenharmony_ci} 460e41f4b71Sopenharmony_ci``` 461