Most of the time you have to use JS to manipulate the DOM. Is this “synchronous” or “asynchronous”?
1. Operate the CHESTNUT of DOM
Normally, in js execution, operations on the DOM are performed synchronously,
<body></body>
<script>
var body = document.querySelector('body');
console.log(`1`);
var cDiv = document.createElement('div');
console.log(cDiv)
console.log(`2`);
body.appendChild(cDiv)
console.log(body);
</script>
Copy the code
The above results are consistent with our expected results, top-down sequential synchronous execution, here highlights, JS engine threads.
So let’s do a little bit of modification
<style>
.easy {
width: 200px;
height: 200px;
background: lightgoldenrodyellow;
}
.hard {
background: lightsalmon;
transition: 2s all;
}
</style>
<body></body>
<script>
var body = document.querySelector('body');
console.log(`1`);
var cDiv = document.createElement('div');
console.log(cDiv);
console.log(`2`);
body.appendChild(cDiv)
console.log(body);
cDiv.classList.add('easy') console.log(`3`); / / = = = = = = = = = = = = = = = = = = = = = =for(var i = 0; i<3000000000; i++); cDiv.classList.add('hard')
console.log(cDiv)
// ======================
</script>
Copy the code
Since is synchronous execution, that before I add the second style hard block, theoretically in the case of blocking the < div > should be the background color is light yellow? But running completely wrong ah, out of the slow not to say, actually straight orange. Here we highlight the GUI rendering thread
Two, to clarify the question
- There is a block, the block does not show the existing style, is it synchronous execution?
console.log()
Is the content not empty, just returns slowly, looks like asynchronous execution?- Overstyling is ignored, but background color overwriting is implemented, why?
Three, answer the questions in turn
-
The order of js execution is not detailed here. Common promises, setTimeout,
-
Since synchronous execution has the effect of “asynchronous”, here is the main point: JS engine thread and GUI rendering thread. That is, the JS engine thread and the GUI rendering thread are mutually exclusive, and this is due to the “synchronization” between threads resulting in an “asynchronous” effect when manipulating the DOM.
-
Why didn’t the
style work? Obviously there is a transition effect. The reason: browser rendering implements optimization strategies that combine styles from the same DOM.
Four,
Js engine thread
withGUI rendering thread
The mutual exclusion between threads causes the pairjs
The “asynchrony” problem with DOM manipulation.GUI rendering thread
Optimizations that can be executed render the resulting style.
The details of the render thread are beyond the scope of this discussion.
Although the cause has been found, the problem seems to remain.
5. Solve problems
If the product must be created from JS div has cool effects (such as the overstyling above). Ha ha ha ha
Direct collation of a self-knowledge of the solution of the problem ideas, here is not just excessive style, similar problems are still effective.
Analysis problem:
- The transition effect is at least from A to B, that is, there are at least two different states;
- As mentioned above
GUI rendering thread
withJs engine
The mutex creates a “synchronous” execution effect, so create<div>
It’s already lagging behind, missing A. - And because of the
GUI rendering thread
Optimization strategy, the final result B will cover everything that can be covered. Missing A (to be overridden) and later rendered to appear indocument
Inside. - It is already B, and there is no A state, and the excessive effect is invalid.
The solution is to make<div>
You have an initial state A and you’re done. (Render the generated DOM to the document ahead of time)
Solution 1:
cDiv.classList.add('easy') / /for(var i = 0; i<3000000000; i++);setTimeout(() => {
cDiv.classList.add('hard')}, 0)Copy the code
Use setTimeout to change the execution queue. This means that the js engine is manually delayed, the JS engine is terminated, the suspended GUI rendering thread is executed, and the transition effect is OK after it has the initial state A.
Solution two (recommended) :
cDiv.classList.add('easy') cDiv.clientLeft; // Any method that triggers page backflow can be cdiv.classlist.add ('hard')
Copy the code
If you can make the JS engine lag, you can also make the GUI render thread advance, using any method that triggers immediate backflow, to make state A previously in the render queue take effect. The relative advantage is that method two is more readable or operable than the same method that triggers backflow, which is a natural pursuit for good teams.