Article directory
I. Introduction
Following the previous iOS page white screen problem due to insufficient mobile device memory, (see the blog post "Advanced Cross-platform Application Development (50) uni-app ios web-view nested H5 project white screen problem analysis and solution ") It is found that during the running of the system, the APP iOS
will frequently appear black screens, black blocks, and white screens.
2. Problem Analysis
The above problems are caused by page rendering problems, which may be caused by page stack overflow and application memory leaks.
After getCurrentPages()
outputting the page stack information, it is found that when the bottom navigation is switched, the page stack information has been cleared, so there is no page stack overflow problem.
Continue to try the APP cache cleaning mechanism, and formulate the cleaning strategy as follows:
Click the current tabitem, scroll or refresh the current page to call the native method plus.cache.clear
to clear the application cache. If you click on a different tabitem, it will definitely trigger a page switch.
// 点击 tab 时触发
onTabItemTap (e) {
// #ifdef APP-PLUS
plus.cache.clear( function () {
console.log( "Clear application cache successful!" );
});
// #endif
},
After the implementation of the clean cache policy, the problem was solved.
From this, is it derived to call uni.setStorage(OBJECT)
(macrotask), uni.setStorageSync(KEY,DATA)
(microtask) and other APIs uni.downloadFile
, and uni.saveFile
is it stored in the device memory?
3. Extended reading
3.1 Page Jump
-
uni.navigateTo(OBJECT)
The page stack is preserved and can benavigateBack
returned by calling. However, there is a problem of page stack overflow, so it cannot be used as a general jump method. -
uni.redirectTo(OBJECT)
The page stack will not be preserved, the previous page cannot be returned, and the defaultpages.json
first page will be returned. -
uni.reLaunch(OBJECT)
Destroy the page stack and jump to the specified page. Usually used to log out and return to the home page. -
uni.switchTab(OBJECT)
Used to switch tabs. -
uni.navigateBack(OBJECT)
CooperatenavigateTo
and return to the page to use, which can effectively avoid page stack overflow. You cangetCurrentPages()
get the current page stack and decide how many layers you need to return.
Through the analysis of the project code, it is found that there is no page stack overflow exception in the routing jump. When the bottom navigation bar is switched, the page stack will be cleared. Only page jumps under the same navigation bar will be in the page stack.
2 Troubleshooting ideas
- According to the specific business scenario, logically control the page jump and return to prevent the page stack from overflowing. By
getCurrentPages()
judging how high the page stack is and checkingwebview
the number of objects, we can judge whether the current jump method is appropriate. - Check the code logic, if there is a problem that the background request does not return for a long time, you can
uni.request
add ittimeout
to avoid this situation. - Check for memory overflow, whether there is a timer created (
setInterval
), but not cleared (clearInterval
). uniapp
The problem itself, because its cross-platform needs tojs
be callednative
, the performance will definitely be lost. If it is unacceptable, it should be developed in native language.- When deleting the cache, it needs to be used if the data is cleared
uni.clearStorageSync
.
Then you need to check the memory occupied by the application during running to see if there is a memory leak.
3.2 In-depth analysis of $nextTick principle
Vue
Realizing responsiveness does not mean DOM
changing immediately after the data changes, but updating according to a certain strategy DOM
. $nextTick
The delayed callback is executed after the end of the next DOM
update cycle. After modifying the data $nextTick
, the updated data can be obtained in the callback DOM
, and the delayed callback is executed after the end of the next DOM
update cycle.
The simple understanding is: when the data is updated and dom
rendered in , the function is automatically executed. The above data will not be updated immediately after Vue
the update , that is to say, if we modify the data in and immediately obtain the above value, what we get is the old value, and we put the operation of obtaining the above value into it, and we can get The updated data.data
DOM
data
DOM
DOM
$nextTick
The correct usage is: after vue changes the data in data, use the vue.$nextTick()
method to wrap the js object to execute the subsequent code.
3.2.1 When to use $nextTick()
Vue
created()
The DOM operation performed by the hook function of the life cycle must be placed Vue.nextTick()
in the callback function. The reason is that created()
when the hook function is executed, the DOM does not actually perform any rendering, and it is useless to perform DOM operations at this time. Different from futile, so here must put the js code of DOM operation into Vue.nextTick()
the callback function.
When the data of the function is changed in the project data
and you want to do something based on the new dom, DOM
you need to put the new series of js operations Vue.nextTick()
into the callback function.
3.2.2 $nextTick() execution principle
Vue
DOM
Updates are performed asynchronously. As long as data changes are detected, Vue
a task queue will be opened and all data changes that occur in the same time loop will be buffered. If the same watcher
is triggered multiple times, it will only be pushed into the queue once. (This deduplication during buffering is very important to avoid unnecessary calculations and DOM
operations )
Then, in the next event loop " tick
", Vue
the queue is flushed and the task queue (deduplicated) work is executed.
Vue
Internally try to use native Promise.then
(microtasks) for asynchronous queues, MutationObserver
and setImmediate
if the execution environment does not support it, it will use setTimeout(fn, 0)
(macrotasks) instead.
3.3 JS operating mechanism
JS
Execution is single-threaded and it's event loop based. The event loop is roughly divided into the following steps:
- All synchronization tasks are executed on the main thread, forming an execution stack ;
- In addition to the main thread, there is also a " task queue " (
task queue
). - As long as the asynchronous task has a running result, an event is placed in the " task queue ".
- Once all the synchronous tasks in the " execution stack " have been executed, the system will read the " task queue " to see what events are in it. Those corresponding asynchronous tasks end the waiting state, enter the execution stack, and start executing. The main thread keeps repeating the third step above.
The execution process of the main thread is a tick, and all asynchronous results are scheduled through the " task queue ". The " task queue " stores tasks one by one. The specification stipulates that tasks are divided into two categories, macro tasks and micro tasks .
3.3.1 Microtasks
Also known as job
, it is usually used for things that happen directly after the currently executing script, such as reacting to a series of behaviors, or doing some asynchronous tasks without creating a new task. javascript
At the end of each task, the microtask queue is processed after the callback, as long as nothing else is executing in the execution stack . Other microtasks queued during the microtask will be added to the end of this queue.
Common microtasks are MutationObsever
, Promise.then
, $nextTiock
.
3.3.2 Macro task
The role of the macro task is to allow the browser to obtain javascript / dom
the content from the inside and ensure that the execution stack can proceed sequentially. Scheduling is everywhere, such as parsing HTML, getting mouse click event callbacks, and so on.
The common macro tasks are setTimeout
, MessageChannel
, postMessage
, setImmediate
;
vue
For DOM update, it is also called internally nextTick
for asynchronous queue control. And when we call it ourselves nextTick
, it adds our own callback function after the micro task that updates the DOM, so as to ensure that our code is executed after the DOM is updated.
setTimeout
It is a macro task: it is only delayed execution. In the delayed execution method, DOM
it may or may not be updated.
3. Solutions
Note ⚠️:
-
uni-app
The built-inHTML5+
engine allows js to directly call rich native capabilities.Conditional compilation call
HTML5+
: There is noHTML5+
extension , so when callinguni-app
the extension specification of , you need to pay attention to the use of conditional compilation.HTML5+
Otherwise,plus is not defined
errors .// #ifdef APP-PLUS var appid = plus.runtime.appid; console.log('应用的 appid 为:' + appid); // #endif
-
uni-app
The logic layer runs in an independent environmentjscore
, which does not depend on the local machinewebview
, so on the one hand, it has no browser compatibility issues and canAndroid4.4
runes6
code on it; on the other hand, it cannot runwindow、document、navigator、localstorage
other browser-specific js APIs.jscore
It is a standard js engine, and standard js can run normally, such as if, for, various strings, date processing, etc. The difference between js and browser should be distinguished. -
uni-app
There is no such thing as an App on the App sidewebkit remote debug
, becauseuni-app
the js does not run inwebview
it, but is independentjscore
. -
Since the browser GUI rendering thread and the JS engine thread are mutually exclusive, when the JS engine executes, the GUI thread will be suspended until the execution of the JS engine ends. When there are many long tasks on the page, it will cause the page UI to be blocked, and the interface will be stuck and frames will be dropped.
GUI rendering threadhtml、css
: responsible for page drawing and rendering, resource parsing, dom tree generation, and page drawing that we are familiar with are all responsible for this thread.
JS engine thread : Responsible for js parsing and execution of all asynchronous and synchronous tasks, maintaining an execution stack, first processing synchronous codes one by one, when encountering asynchronous tasks, it will use events to trigger threads.
The process and thread information of the browser is as follows:
Among them, the front-end mainly focuses on the rendering process of the browser kernel, which is mainly responsible for html、css、js
resource parsing and rendering, and is also responsible for event loops and asynchronous requests.
Data storage: Are the cache and H5 cache in uni-app stored in memory?
-
The native
plus Storage
module manages the application's local data storage area, which is used for saving and reading application data. The difference between application local data and andlocalStorage
is that the data is valid in different domains . The former can be operated across domains within the application. The data storage period is persistent and there is no capacity limit. Through can get application local data management object.sessionStorage
plus.storage
-
uni-app
When applicationsuni.setStorage(OBJECT)
(macrotasks) anduni.setStorageSync(KEY,DATA)
(microtasks) store data, the essence is to use nativeplus.storage
, no size limit, not cache, but to store data insqlite
database files for persistence. -
The App also supports local storage solutions such as SQLite and IO files .
-
For H5 applications
localStorage
andsessionStorage
data storage, the browser limits the size to 5M, which is a cache concept and may be cleaned up. -
The application
Vuex
implements state management. -
Native
plus.cache
management application cache data includes onlywebview
the data generated in the program, and does not include the data saved in the business logic using extensionsapi
(such asuni.setStorage(OBJECT)
(macrotask),uni.setStorageSync(KEY,DATA)
(microtask) and other APIs). -
Each applet comes with its own
storage api
, and the data storage life cycle is consistent with the applet itself, that is, unless the user actively deletes or is automatically cleaned up after a certain period of time, the data is always available. -
uni-app
For problems that cannot be solved by the framework components themselves, the framework components can be discarded and optimized using native components.
In the end, choose to do cache cleaning when switching the bottom tab. Note that the cache cleaning here is used plus.cache.clear
to clear the cache data of the application. Clearing application cache data only includes webview
data generated by use in the program, and does not include api
data saved by extensions in business logic. code show as below:
// 点击 tab 时触发
onTabItemTap (e) {
console.log('-----------点击 tab 时触发-----------', e);
// #ifdef APP-PLUS
plus.cache.clear( function () {
console.log( "component Clear application cache successful!" );
});
// #endif
},
4. Extended reading
- uni-app route navigation
- uni-app getCurrentPages()
- HTML5+ API
- Notes for uni-app using HTML5+
- Android platform storage performance optimization instructions
- onTabItemTap
- " Advanced Cross-platform Application Development (50) uni-app ios web-view nested H5 project white screen problem analysis and solution "