Detailed explanation of transition-group principle

The transition-group component is different from the transition component and will be rendered as a real element. If we don't define the tag attribute, the default is span. It has all the features of transition and has its own unique render method:

1. rawChildren is to store the default slot value;

2. preChildren is to store the last child node (because nodes can be added and deleted);

3. children is to store the current child node containing the key;

4. Obtain transitionData data from transition-group properties and events through the extractTransitionData method;

5. Traversing rawChildren, only nodes with key are added to children (this is why each child node of transition-group must have a key, even if v-for is used);

6. Add a transition attribute to the data attribute of each current child node, and the value is transitionData;

7. If there is preChildren, then traverse it, and then keep the last position of each child node (record the initial position for smooth movement), add the child nodes that will be rendered twice to the kept array, and there will be only the last time The rendered child nodes are added to the removed array;

8. Create a rendering vnode (tag defaults to span) through the createElement function, pass in kept as a child node parameter, and copy the value to this.kept;

9. Finally, render will return one: create a rendering vnode through the createElement function, and pass in the children array as a child node parameter.

transition-group has built-in FLIP animation (when the final state is unknown), so when we add or delete a node, other nodes will move smoothly instead of abruptly:

F is First, which records the initial state of the element and records it before the element moves;

L is Last, which records the final state to which the element is to be moved, and records it after the element is moved;

I is Invert, that is, first calculate the difference between the initial state and the final state, and then move the element to the initial state through transform (pass the difference to transform). After this step, a forced redrawing is required, because when rendering the node It will go through several processes (calculations). In a synchronous queue, when the rearrangement calculation reaches this position, it will trigger redrawing to present the elements at this position, otherwise only the final calculation result in one tick will be presented;

p is play, that is, the animation easing process. First use transition to monitor the change of transform or all, and then set the transform property to 0, and we can see the easing.

If you want to fully understand the knowledge mentioned above, Google the FLIP principle yourself, and then read this article: Rearrangement and redrawing

In addition to the method mentioned in the article (synchronous process), we can also use an asynchronous method (because it is not in the same tick) to trigger redrawing. Generally, requestAnimationFrame is used to render animations (execute code in the next frame), and of course You can use asynchronous methods such as setTimeout, but the first method is that there will be no lag, the reason is here: requestAnimationFrame detailed explanation .

In our example, the deletion and addition of nodes will also move up and down, because when adding the following two classes, it is executed in the function encapsulated by requestAnimationFrame in the transition component characteristics:

.list-complete-enter-active {   transition: all 1s; }
.list-complete-leave-active {   transition: all 1s;   position: absolute; }

Let's take a look at how transition-group achieves the characteristics of moveClass. The core code is in the update hook in the transition-group component (this function will be triggered when the data is modified):

1. Obtain moveClass. If the moveClass attribute is not defined in the transition-group component node, then move is spliced ​​after the name attribute value;

2. If there is no child node or it is detected that the child node does not listen to transform or all through transition (detected through the hasMove function), then return directly;

3. Traverse the children and execute the callPendingCbs function. Since the entire transition is asynchronous, if the updated hook is triggered before the end of the previous transition, then the callback function for the end of the previous moveCb or enterCb animation will be executed immediately to ensure that the entire execution is no problem of;

3. The second traversal of children executes the recordPosition function, retaining the current position of each child node (recording the final state for smooth movement);

4. The third traversal of children executes the applyTranslation function, and calculates the difference between the initial state and the final state of each child node. If the difference is not zero, then immediately move the element from the final state to the initial state through transfrom, and transfer this node The data.move is set to true, indicating that this node needs to be slowed down;

5. Force redrawing through offsetHeight, then the node will be presented in the initial state (only the final calculated position will be presented in the same tick);

6. Traverse the children again, add moveClass to the child nodes that need to be moved (make the node have a transition class attribute, monitor the change of transform or all), remove the transform class attribute, add the transitionEndEvent event, the callback function is moveCb, and clear the transitionEndEvent event , remove moveClass, and set el._moveCb to null, indicating that the callback function has been executed.

Therefore, there are three ways to make the child nodes of the transition-group component have a easing effect: 1. Add the moveClass attribute to the transition-group component node, customize the class name, and then add transition to the class in the style; 2. Directly in the style 3. Add a custom class name to each child node, and then add a transition to the class in the style.

Then, it should be noted that the display of the child node cannot be inline. If the default is inline, it must be written as inline-block, so that the FLIP animation will take effect. This is a special reminder on the Vue official website.

Finally, let’s talk about the beforeMount hook of the transition-group component. Since the updateChildren function will move the elements, the deleted node may not be in the original position, so the _update function is rewritten and the patch function is executed twice. A patch only deletes all the nodes that need to be deleted without moving (set the removeOnly parameter to true), and then triggers the leaving transition of the deleted nodes (so that the deleted nodes are in the correct position when performing animation); the second patch is Insert new nodes or move nodes to final state.

So here, the implementation principle of the transition-group component is introduced. Compared with the transition component, it realizes the transition of the list, and it will be rendered into a real element. When we modify the data of the list, if we add or delete data, the transition animation of the corresponding element itself will be triggered, which is the same as the transition component. In addition, transition-group also realizes the transition effect of move , making our list transition animation richer.

Reference from transition-group

おすすめ

転載: blog.csdn.net/coinisi_li/article/details/126886026