setTimeout()
is a JavaScript method you have to carefully use because it directly affects the browser or visible performance.
Fundamentally, what does setTimeout()
method stand for?
from MDN,
The
setTimeout()
method of theWindowOrWorkerGlobalScope
mixin sets a timer which executes a function or specified piece of code once the timer expires.
That’s it. it’s a timer function.
Therefore, it seems only be meaningful when it with a certain number of delay-time, but actually it is not.
There are some cases you can use setTimeout()
with no delay-time (this means 0 delays).
Check out the example write down by Vue.js
and Ant Design Vue
.
Don’t worry, React
and Angular
fellas. This is just a concept.
<template>
<button @click="toggleTree">open</button>
<div v-if="isModalOpened">
<a-tree
v-model="checkedKeys"
checkable
:expanded-keys="expandedKeys"
:auto-expand-parent="autoExpandParent"
:selected-keys="selectedKeys"
:tree-data="treeData"
@expand="onExpand"
@select="onSelect"
/>
</div>
</template>
<script>
export default {
// ...
methods: {
toggleTree() {
this.isModalOpened = !this.isModalOpened;
document
.querySelectorAll('.ant-tree-switcher')
.forEach((item) => item.remove());
},
// ...
},
// ...
};
</script>
a-tree
tags are just copied from the official Ant-design-vue Website.
My object here is to remove the default Ant-design-tree
open function(Triangle Icon) so that no one can expand and shrink the tree list.
I add document.querySelectorAll()
in toggleTree()
function which is toggling tree module. you can use refs
method instead, but it should use very carefully. It sometimes messes up the work when handling third-party modules.
.ant-tree-switcher
class is a default class of DOM
for those tree openers.
From this code, it would catch tree openers of the Ant-design-tree
module then remove them when opening the modal.
Here is Codepen example down below. Click the open
button.
As you see, it doesn’t work at all.
why? Code seems fine and simple logic.
From now, it is the time to roll!
let’s call out our hero, setTimeout(fn,0)
here.
<template>
<button @click="toggleTree">open</button>
<div v-if="isModalOpened">
<a-tree
v-model="checkedKeys"
checkable
:expanded-keys="expandedKeys"
:auto-expand-parent="autoExpandParent"
:selected-keys="selectedKeys"
:tree-data="treeData"
@expand="onExpand"
@select="onSelect"
/>
</div>
</template>
<script>
export default {
// ...
methods: {
toggleTree() {
this.isModalOpened = !this.isModalOpened;
setTimeout(() => {
document
.querySelectorAll('.ant-tree-switcher')
.forEach((item) => item.remove());
}, 0);
},
// ...
},
// ...
};
</script>
Nothing changed except setTimeout()
wrapping document.querySelectorAll()
method.
Check out the new Codepen example below.
the tree opener is gone!
Why works? or why didn’t work before?
Only difference is setTimeout()
.
Here is the original stack flow.
toggleTree()
this.isModalOpened
updated the status of ant-desgin-tree
module, then mounted it.ant-desgin-tree
module loaded some expensive job, document.querySelectorAll()
method was called before loading default DOM
such as tree opener
which is the target to remove.document.querySelectorAll()
method did’t catch anything (returned undefined
). Nothing could change.toggleTree()
this.isModalOpened
updated the status of ant-desgin-tree
module, then mounted it.ant-desgin-tree
module loaded some expensive job, (microtask
) setTimeout(fn,0)
method made document.querySelectorAll()
method assigned as a task
. Therefore, document.querySelectorAll()
method waited until finishing all expensive microtask
from ant-design-tree
module.ant-design-tree
module, document.querySelectorAll()
method was called, and caught every DOM
we intended to remove.If you still don’t understand about Browser call stack, check other posts here below the link.
That’s it!
That’s all about setTimeout(fn, 0)
method. It makes jobs synchronously which is sometimes not available to handle by Promise
.