Proper Usage of setData
setData is the most frequently used and also the most common cause of performance issues in mini-program development.
1. Process of setData
The process of setData can be roughly divided into several stages:
- Transferring data from the logic layer to the view layer.
- Updating the virtual DOM tree in the view layer, updating the real DOM elements, and triggering page rendering updates.
2. Data Communication
For the first step, because the logic layer and the view layer of the mini-program are two independent execution environments, belonging to different threads or processes, they cannot directly share data. Therefore, data communication is asynchronous and non-real-time.
The time it takes for data transmission is positively correlated with the size of the data. If the receiving end thread is busy, the data will wait in the message queue.
3. Usage Recommendations
3.1 Data Should Only Include Rendering-Related Data
setData should only be used for updates related to rendering. Using setData to update fields unrelated to rendering will trigger additional rendering processes or increase the amount of transmitted data, affecting rendering time.
- ✅ The
data
field of a page or component should only store data related to rendering (i.e., fields that appear directly in dlt). - ✅ Data indirectly related to rendering can be set as "pure data fields" and updated using setData, with changes observed through observers.
- ✅ Data unrelated to rendering should be stored in non-data fields, such as
this.userData = {userId: 'xxx'}
. - ❌ Avoid including business data unrelated to rendering in the data.
- ❌ Avoid using data for data sharing between page or component methods.
- ❌ Avoid abusing "pure data fields" to store data that could be stored in non-data fields.
3.2 Control the Frequency of setData Calls
Each setData call triggers the traversal and update of the logic layer's virtual DOM tree and may also lead to a complete page rendering process. Calling setData too frequently (on a millisecond scale) may result in the following consequences:
- The logic layer JS thread remains busy, unable to respond to user-operated events normally or complete page switches.
- The view layer JS thread remains busy, increasing the communication time between the logic layer and the view layer. The view layer receives messages with high delays, causing noticeable rendering delays.
- The view layer cannot respond promptly to user operations, causing obvious lag when users scroll the page, delayed feedback on operations, and user-operated events not being promptly transmitted to the logic layer, which also cannot promptly transmit the results of operation processing to the view layer.
Therefore, developers should pay attention to the following when calling setData:
- ✅ Only call setData when updates to page content are necessary.
- ✅ Try to merge consecutive setData calls as much as possible.
- ❌ Avoid unnecessary setData calls.
- ❌ Avoid continuously calling setData at a high frequency, such as on a millisecond scale, such as for countdowns.
- ❌ Avoid calling setData on high-frequency events, such as in scroll callbacks.
3.3 Only Pass Changed Data to setData
The amount of data passed to setData affects the time it takes for data copying and communication, increasing the overhead of page updates and causing delays in rendering.
- ✅ Only pass fields that have changed to setData.
- ✅ It is recommended to change a specific item in an array or a specific property of an object using data paths, such as
this.setData({'array[2].message': 'newVal', 'a.b.c.d': 'newVal'})
, instead of updating the entire object or array each time. - ❌ Do not be lazy and pass all data at once in setData:
this.setData(this.data)
.
3.5 Control setData for Background Pages
Because the mini-program logic layer runs on a single thread, setData by background pages will also compete for the foreground page's execution resources, and the rendering of background pages is not perceivable by users, resulting in waste. On some platforms, the WebView of the mini-program rendering layer also shares the same thread. Rendering and logic execution of background pages may cause foreground page stuttering.
- ✅ Avoid performing update operations after switching to the background, or delay them until after the page is shown again.
- ❌ Avoid using setData at a high frequency after switching to the background, such as for countdown updates.