The previous section discusses the recursive descending algorithm, but when the state machine stops is not introduced, that is, the judgment logic of the isEnd() function. In order to figure out this problem, we need to simulate the running process of the state machine.
As mentioned earlier, when calling the parseElement function to parse the tag node, the parseChildren function will be called recursively, thereby opening a new state machine. After the state machine is executed, the parent node stack is empty, all state machines stop running, and the template parsing is completed
If the state chance encounters a state that does not meet the expectations, you can withdraw this by using the following code of the parseChildren function:
function parseChildren(context, ancestors){ let nodes = [] const { mode } = context while(!isEnd(context, ancestor)){ let node if(mode === || mode === ){ if(mode=== && [0] === '<'){ if([1] === '!'){ // Some codes are omitted }else if([1] === '/'){ // The state machine encounters a closed tag, and an error should be thrown at this time because it lacks the corresponding start tag ('Invalid end tag') continue }else if(/[a-z]/i,test([1])){ // Some codes are omitted } } else if (('{{')) [ // Some codes are omitted } } // Some codes are omitted } return nodes }
In other words, if we analyze the template in the above example according to our current implementation idea, the final error message is: "Invalid end tag".
But in fact, there is another better way to analyze it. Observe the template given in the above example, where there is a complete paragraph, as follows:
<div><span></div></span>
You can see that there is a complete piece of content in the template. We hope that the parser can parse it normally, which is likely to be in line with the user's intention.
But in fact, no matter which interpretation method, it will have little impact on the program. The difference between the two is reflected in error handling. For the first explanation, the error message we get is "Invalid end tag". For the second explanation method, after the "Complete Content" part is parsed, the parser will print the error message:<span>
The tag lacks a closed tag. Obviously, the second explanation is more reasonable
In order to implement the second explanation method, we need to adjust the logic of the isEnd function. When determining whether the state machine should stop, it should not always be compared with the parent node at the top of the stack, but with all nodes in the entire parent node stack. As long as the parent node stack exists in the node with the same name as the end tag currently encountered, the state machine will be stopped, as shown in the following code:
function isEnd(context, ancestors){ if(!) return true // Compare with all nodes in the parent node stack for(let i = -1;i>=0;--i){ //Stop the state machine as long as there is a node in the stack with the same name as the current end tag. if((`</${ancestors[i].tag}`)){ return true } } }
Perform analysis of the following templates according to the new idea:
<div><span></div></span>
The process is as follows:
- "State Machine 1" encountered
<div>
Start the tag, call the parseElement parse function, and enable the "State Machine 2" parse child nodes. - "State Machine 2" encountered
<span>
Start signing, call the parseElement parsing function, and enable the "State Machine 3" parsing child nodes. - "State Machine 3" encounter
</div>
End tag, because there is a tag node named div in the node stack, "state machine 3" stops.
In this process, when "state machine 2" calls the parseElement solution function, the parseElement function can discover<span>
The closed tag is missing, so the error message will be printed "<span>
The tag is missing a closed tag, as shown in the following code:
function parseElement(context, ancestors){ const element = parseTag(context) if() return element (element) = parseChildren(context, ancestors) () if((`</${}`)){ parseTag(context, 'end') }else{ (`${}Label missing closed tag`) } return element }
This is the end of this article about the detailed explanation of the operation of Vue state machine opening and stopping. For more related Vue state machine content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!