In this paper, through practical business examples, how to transfer the state machine idea and apply it to the actual business development scenarios, so as to help us simplify the complex multi-state flow scenarios in development.
1. Practical problems
First, describe the requirement background. A search page is to be implemented in the project. The main logic of the search page is roughly as follows:
- When the user does not enter, the shortcut input panel is displayed:
- When the user enters in the search box, the list of associative input is displayed:
- When determining the search keyword, select from the shortcut panel or Association panel, enter the search box, and press Enter to display the list of search results:
After analyzing the requirements, a rule can be concluded: according to the different operations of users, the corresponding functions need to be presented.
The above scenario conforms to the three characteristics of finite state machines:
- The number of State machines is finite
- In one state at any one time
- When an Event is met, there is a Transition from one state to another, and an Action is performed at the same time.
Then, using the idea of state machine, will describe the user’s different state flow, will it be more clear?
Concept 2.
Let’s first look at the definitions of the four core concepts of finite state machines:
- State: Includes the initial State and the State after the event is triggered. There must be a final State.
- Event: Triggers the state machine to switch from one state to another.
- Transition: To change from one state to another. The event that causes the state transition is called a triggering event.
- Action: Indicates the specific Action to be performed after the state transition.
3. In the actual scene, how to use the idea of state machine abstraction?
S1: Extraction state: the operation stage of the user is divided, enumerating the existing state
- Before input (initial state)
- The state being entered
- Result after input (final state)
S2: Define actions – find out the corresponding behavior after moving to each state
- Display the shortcut input panel
- Displays a list of associative inputs
- Displays a list of search results
S3: Identify events – identify the conditions that trigger state transitions
A state transformation diagram is used to describe the transformation relationship between states:
4. How?
S1: Define the value of a variable according to the partition state
SearchStatus is used to represent the searchStatus of the search page, i.e. Before-input, doing-input, after- confirm the input result (including: enter the keyword to confirm, click the association list, and popular and historical rules).
data() {
return {
searchStatus: 'before'.// This page is entered for the first time by default
searchResult: ' ' // Record search results}}Copy the code
S2: Components are split according to states and corresponding actions of each state and associated with each state value
Split the entire search page into two parts:
The first part is: the common search box in all three states
<div class="keyword-search">
<search-input
ref="searchInput"
placeholder="Search"
@debounce-input="valueChange"
@keyup="keyup"
@cancel="cancelSearch"
></search-input>
</div>
Copy the code
The second part shows the corresponding components in the three states by switching different states. Include:
- Hot search, history search panel components
In the initial state of input, the hot search and history search panels should be displayed. Here, this. SearchStatus === ‘before’ controls whether to display.
<search-option-panel
v-if="searchStatus === 'before'"
title="Hot Search rules"
@click="selectHotResult"
></search-option-panel>
<search-option-panel
v-if="searchStatus === 'before'"
title="Search History"
@click="selectKeywordOption"
@clear="clearSearchHistory"
></search-option-panel>
Copy the code
- A list of associative inputs
In the input box, when the user inputs words, that is, in the input, the list of associative input should be displayed, including when the user inputs unrelated associative words, there is no relevant logic related to the content. Here, this. SearchStatus === ‘doing’ controls whether to display.
<div class="related-keyword-list-wrapper" v-if="searchStatus === 'doing'">
<div class="related-keyword-list" v-if="relatedKeywordList.length">
<div class="keyword-option border-bottom-1px"
v-for="(value, index) in relatedKeywordList"
:key="index"
@click="selectKeywordOption(value)">
{{value}}
</div>
</div>
<div v-else class="no-keyword-list-wrapper">
<div class="no-data-icon"></div>
<div class="no-data-tip">Sorry, no relevant results found.</div>
<div class="no-data-suggest">Try other keywords</div>
</div>
</div>
Copy the code
- List of search results
After taking user input, a list of search results should be displayed. Here, use this.searchStatus === ‘after’ to control the display of the list of results. After the user manually enters (enter to confirm), or selects from the search association list, and popular and historical rules, sets searchStatus to after, stores the selected search results in searchResult, and displays the list of search results. This part of the logic also includes the user input no related results, the relevant logic prompt no content related.
<list ref="list" v-if="searchStatus === 'after' && searchResult"></list>
Copy the code
S3: Switches different status values based on events
(For ease of understanding, only the key logic that controls state switching is reserved for the following code.)
methods: {
// Select the keywords in the hot search panel
selectHotResult(val) {
this.searchStatus = 'after'
this.searchResult = val
},
// Select the keyword in the history search panel, and select the search association
selectKeywordOption(val) {
this.searchStatus = 'after'
this.searchResult = val
},
// After entering the search term, press Enter to confirm
keyup($event) {
if ($event.keyCode === 13) {
this.searchStatus = 'after'
this.searchResult = this.searchValue
}
},
// Click the cancel button in the search box
cancelSearch() {
if (this.searchStatus === 'before') {
this.$router.go(-1)}else {
this.searchStatus = 'before'
this.searchResult = ' '
this.$refs.searchInput.clearValue()
}
},
// Enter the keyword in the input box
valueChange() {
this.searchStatus = 'doing'
this.searchValue = v
this.searchResult = ' '. }}watch: {
searchResult: {
handler(value) {
if(! value) {return
}
this.searchStatus = 'after'. }}}Copy the code
conclusion
The idea of a state machine is applicable to business scenarios where different functions need to be controlled based on multiple states. The developer only needs to focus on the control of the state and care about rendering the corresponding behavior of each state. Each set of states, behaviors, and results are independent of each other, even if each group changes later.
In actual development scenarios, when we encounter multiple states and complex branches, we can consider using the idea of state machine to comb logic, so as to help us comb business logic more clearly and quickly, and avoid using huge and tedious conditional statements.