preface

The application of Design Pattern in VUE (1) The application of design pattern in VUE (2) the application of design pattern in VUE (3) the application of design pattern in VUE (4) The application of design pattern in VUE (5) the application of design pattern in VUE (6) The application of design pattern in VUE (7)

Why write these articles. Just as Design Pattern is a set of repeatedly used, known by most people, classified and summarized code Design experience (from Baidu Encyclopedia), I also want to discuss the charm of Design Pattern with everyone through sharing some accumulated work. The application scenarios introduced in this series of articles as an aid to illustration are real application scenarios in the workplace, of course, but common business scenarios are also covered by analogy



This article is relatively simple and covers only one design pattern — the state pattern.

A, demand

The image is a screenshot from the iView document

The requirement now is that the entire process is continuous, and unless the whole process is complete, every step of the page refresh should be restarted from the first step, that is, all four steps should be processed under the same route

Second, analysis

At the beginning of the article, we mentioned the state mode, which can be easily associated with the above requirements:

  • Step 1 completes the change of state to step 2
  • Step 2 operation completes change state to step 3
  • Step 3: Change the state to step 4

Three, the design

Let’s start with the introduction of state mode

The following content is from the Internet

First, you need a context environment role
// context.vue
<template>
  <div>
    <Steps :current="status">
      <Step title="Done" content="Here's the first step."></Step>
      <Step title="In progress" content="Here's step two."></Step>
      <Step title="Pending" content="Here's step three."></Step>
      <Step title="Pending" content="Here's step four."></Step> </Steps> <! -- Dynamic render current state component --> <component :is="statusCom" @onChangeStatus="changeStatus"/> </div> </template> <script> // import Step1 from'./Step1'
  import Step2 from './Step2'
  import Step3 from './Step3'
  import Step4 from './Step4'
  
  export default {
    data() {
      return{status: 1}}, computed: {// Specify a status rolestatusCom() {
        const statusMap = {
          1: Step1,
          2: Step2,
          3: Step3,
          4: Step4,
        } 
        returnChangeStatus (val) {this.status = val}} </script>Copy the code
2. Implement the abstract State role
// Step1.vue <template> <div> <! --do something -->
    <button @click="handleClick"</button> </div> </template> <script>export default {
    methods: {
      handleClick() {// The first step is complete, change the state to state 2 // context role accepts the state change dynamic render step2.vue operation this.$emit('onChangeStatus', 2)
      }
    }  
  }
</script>
Copy the code
Step2.vue step3. vue step4. vue is the same as step1.vueCopy the code
3,
  • The context role is only responsible for switching the specific state — which step of the component to render
  • The state role handles the implementation of the current state and switching to the next state — the concrete implementation of the logic at each step

Four, optimize

Through the above implementation, we find that the entire state change is assigned to each state component. What if I go to step 3 and want to go back to step 2?

Give each state component a fallback to the previous state? In our requirement, the states are unidirectional from 1->2->3->4, which may work. Suppose that in a complex state scenario, the changes of states are disorderly and it is difficult to determine what is the next state of the current state

Solution: Cache each state change

// Context. vue <template> <div> <Steps :current="status">
      <Step title="Done" content="Here's the first step."></Step>
      <Step title="In progress" content="Here's step two."></Step>
      <Step title="Pending" content="Here's step three."></Step>
      <Step title="Pending" content="Here's step four."></Step> </Steps> <! --> <button v-if="canGoBack" @click="goBack"</button> <! -- Dynamic render current state component --> <component :is="statusCom" @onChangeStatus="changeStatus"/> </div> </template> <script> // import Step1 from'./Step1'
  import Step2 from './Step2'
  import Step3 from './Step3'
  import Step4 from './Step4'
  
  const DEFAULT_STATUS = 1
  
  export default {
    data() {
      return{status: DEFAULT_STATUS, cache: [] // Cache status}}, computed: {// Specific status rolestatusCom() {
        const statusMap = {
          1: Step1,
          2: Step2,
          3: Step3,
          4: Step4,
        } 
        return statusMap[this.status]
      },
      canGoBack() {
        returnthis.cache.length > 0 } }, methods: ChangeStatus (val) {this.cache.push(val) this.status = val},goBack. () {/ / pop up the current state of this cache. The pop () / / change the state to a state this. The status = this. Cache [. This cache. The length - 1] | | DEFAULT_STATUS}}} </script>Copy the code

conclusion

State patterns are introduced through a functional design at work. Maybe some students will say that I can also do it by if else. Of course, as the requirements keep changing, only you can understand your if else eventually, and gradually the chance of bugs will become higher. The state mode is used to solve this problem


This implementation also applies to react. Why vue? The React JSX template can be a bit awkward to understand, while the React JSX template can be seen as writing JavaScript to implement more flexible concepts