Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use the mounted hook in vue

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly shows you "how to use mounted hooks in vue". The content is simple and clear. I hope it can help you solve your doubts. Let me lead you to study and learn this article "how to use mounted hooks in vue".

Note: reading this article requires a clear understanding of the patch process of vue. If you are not clear about the patch process, it is recommended to understand this process before reading this article, otherwise you may feel foggy.

Before we talk, let's look at a scene.

As shown above, there are two subcomponents in the App.vue file, which are brothers to each other.

There are two life cycle hooks, created and mounted, in the component. An indicates that the component name C is the abbreviation of created.

/ / a component created () {console.log ('aC')}, mounted () {debugger console.log (' aM')}, / / b component created () {console.log ('bC')}, mounted () {debugger console.log (' bM')}

What is the printing order, please? Readers can make up for it first and see if it is correct later.

Readers who are familiar with the vue patch process may think that the order is aC → aM → bC → BM, that is, component an is created, then mounted, and then repeated in component b As you can see from the patch method, the process of entering the parent container from component created to insert is a synchronous process. Only after this process is completed will it traverse to component b and follow the rendering process of component b.

In fact, the order in which the browser prints out is aC → bC → aM → bM, that is, two created are executed first and then executed in mounted, which is contrary to the above analysis. First of all, the reason is that the process of the child component entering the parent container from created to insert is synchronous, but after insert enters the parent container, it can also be understood as the child component mounted, and the mounted lifecycle hook is not called immediately. Let's analyze it from the perspective of source code:

First, briefly review the sub-component rendering process. The patch function calls createElm to create a real element,createElm. Use createComponent to determine whether the current vnode is a component vnode. If so, enter the component rendering process.

Function createComponent (vnode, insertedVnodeQueue, parentElm, refElm) {var I = vnode.data; if (isDef (I)) {var isReactivated = isDef (vnode.componentInstance) & & i.keepAlive; if (isDef (I = i.hook) & & isDef (I = i.init)) {I (vnode, false / * hydrating * /);} if (isDef (vnode.componentInstance)) {initComponent (vnode, insertedVnodeQueue) / / after the final component is created, the el corresponding to the component will be inserted into the parent node insert (parentElm, vnode.elm, refElm); if (isTrue (isReactivated)) {reactivateComponent (vnode, insertedVnodeQueue, parentElm, refElm);} return true}

In createComponent, the el corresponding to the component is inserted into the parent node, and finally it is returned to the patch call stack, calling the

InvokeInsertHook (vnode, insertedVnodeQueue, isInitialPatch)

Because the subcomponent has a vnode.parent, it takes a branch, but let's also see what the insert called by the second branch is

Function invokeInsertHook (vnode, queue, initial) {/ / delay insert hooks for component root nodes, invoke them after the / / element is really inserted if (isTrue (initial) & & isDef (vnode.parent)) {vnode.parent.data.pendingInsert = queue;} else {for (var I = 0; I < queue.length; + + I) {queue [I] .data.hook.insert (queue [I]);}}

The insert is hung on the vnode.data.hook. During the component creation process, there is a call to the createComponent method.

InstallComponentHooks, this is where the insert hook is injected. This method is actually defined in the componentVNodeHooks object, and you can see that callHook (componentInstance, 'mounted') is called in this insert, which is actually the mounted life cycle of the calling subcomponent.

Insert: function insert (vnode) {var context = vnode.context; var componentInstance = vnode.componentInstance; if (! componentInstance._isMounted) {componentInstance._isMounted = true; callHook (componentInstance, 'mounted') } if (vnode.data.keepAlive) {if (context._isMounted) {/ / vue-router#1212 / / During updates, a kept-alive component's child components may / / change, so directly walking the tree here may call activated hooks / / on incorrect children. Instead we push them into a queue which will / / be processed after the whole patch process ended. QueueActivatedComponent (componentInstance);} else {activateChildComponent (componentInstance, true / * direct * /);}

Looking at this method again, the subcomponent takes the first branch and executes only one line of code vnode.parent.data.pendingInsert = queue, which queue is actually the insertedVnodeQueue defined at the beginning of the patch. The logic here is to hang the current insertedVnodeQueue on the pendingInsert of parent's vnode data.

Function invokeInsertHook (vnode, queue, initial) {/ / delay insert hooks for component root nodes, invoke them after the / / element is really inserted if (isTrue (initial) & & isDef (vnode.parent)) {vnode.parent.data.pendingInsert = queue;} else {for (var I = 0; I < queue.length; + + I) {queue [I] .data.hook.insert (queue [I]) At the beginning of patch, insertedVnodeQueue is defined as an empty array var insertedVnodeQueue = []

If you search insertedVnodeQueue in the source code, you can see that there is such a logic that initComponent is still called in createComponent.

Function initComponent (vnode, insertedVnodeQueue) {if (isDef (vnode.data.pendingInsert)) {insertedVnodeQueue.push.apply (insertedVnodeQueue, vnode.data.pendingInsert); vnode.data.pendingInsert = null;} vnode.elm = vnode.componentInstance.$el; if (isPatchable (vnode)) {/ / ⚠️ Note this method invokeCreateHooks (vnode, insertedVnodeQueue); setScope (vnode) } else {/ / empty component root. / / skip all element-related modules except for ref (# 3455) registerRef (vnode); / / make sure to invoke the insert hook insertedVnodeQueue.push (vnode);}}

InsertedVnodeQueue.push.apply (insertedVnodeQueue, vnode.data.pendingInsert) focuses on this line of code, push each item of the vnode.data.pendingInsert array into the insertedVnodeQueue of the current vnode, note that here is through the apply way, so every item of the array vnode.data.pendingInsert is push, not the list of push pendingInsert. That is to say, here, the component collects the item in the insertedVnodeQueue of its subcomponents, because rendering is a deep recursive process, and the insertedVnodeQueue of all the final root components can get every item in the insertedVnodeQueue of all subcomponents.

From the line queue [I] .data.hook.insert (queue [I]) of invokeInsertHook, you can see that the item in insertedVnodeQueue should be vnode. Search for insertedVnodeQueue.push in the source code and you can find that it is the invokeCreateHooks method that puts the current vnode push into it.

Function invokeCreateHooks (vnode, insertedVnodeQueue) {for (vari $1 = 0; iTun1 < cbs.create.length; + + iTun1) {cbs.create [iTun1] (emptyNode, vnode);} I = vnode.data.hook; / / Reuse variable if (isDef (I)) {if (isDef (i.create)) {i.create (emptyNode, vnode) } / / send the current vnode push to insertedVnodeQueue if (isDef (i.insert)) {insertedVnodeQueue.push (vnode);}

For the component vnode, this method is also called in initComponent.

At this point, it is very clear that after the child component insert enters the parent node, the mounted hook will not be called immediately, but the component corresponding to vnode will be inserted into the insertedVnodeQueue of the parent vnode, recursive layer by layer, and finally the root component will get the vnode of all child components, and then loop through it in turn, calling the insert hook of vnode, thus calling the mounted hook. Here is first-in, first-out, and the first one entered by push is called first out, so the mounted of the deepest subcomponent is executed first. Finally, a diagram of source code debugging is attached, and you can clearly see what the insertedVnodeQueue of the root component is.

As for why vue is designed in this way, it is because the mount is the first son after the father, and the child component is inserted into the parent node, but the parent node has not really been inserted into the page, if the mounted of the child component is called immediately, it may cause confusion to the framework users, because the child component does not really render to the page when the mounted is called, and it is certainly impossible to operate dom through the document.querySelector way at this time.

The above is all the contents of the article "how to use mounted hooks in vue". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report