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



Today’s main topic is the most common design pattern we use in framework development (e.g. Vue, React) :

The template method pattern defines the skeleton of an algorithm in a method, deferring the implementation of some steps to subclasses. The template approach allows subclasses to redefine the concrete implementation of certain steps in an algorithm without changing the structure of the algorithm

OOP implementation

1. Algorithm skeleton

An animal body structure algorithm has: head, body, feet

// Template class // Note: JavaScript does not have the concept of an interface, and has certain defects compared to traditional OOP implementations.constructor() {}
  head () {}
  body () {}
  foot () {}
  renderHead () this.body() this.foot()}} {// algorithm procedure ———— body parts order head, body, foot() // render method cannot be overridden by subclasses, cannot be implemented by JavaScript itself, need to comply with this.head() this.body() this.foot()}}Copy the code

2. Implementation of subclass algorithm

Class Pig extends AnimalTemplate {head () {
    console.log('head from pig')}body () {
   console.log('body from pig')}foot () {
    console.log('foot from pig'}} const pig1 = new Pig() pig1.render()head () {
    console.log('head from chicken')}body () {
   console.log('body from chicken')}foot () {
    console.log('foot from chicken')}} const chicken1 = new Chicken() chicken1.render() // execute algorithmCopy the code

React implementation

React has a class component that uses OOP implementations like this, but the method of inheritance seems to be less popular in React than in functional programming (props pass).

1. Here’s a common scenario

class Parent {
  constructor() {}
  render () {
    <div>
      <div name="tom"></div> <! Children render in div with name Joe --> <div name="joe">{this.props.children}</div>
    </div> 
  }
}
class Stage {
  constructor() {}
  render<div>child</div> </ parent >}}Copy the code

So we are already using the template method pattern when we write JAX

2. Implement the OOP completed example again

// Class AnimalTemplate {constructor() {... }render() {// Algorithm process ———— the order of head, body and feetreturnRenderHead ()} {this.props. RenderBody ()} {this.props. RenderFoot ()} </div>)}}constructor() {}
  pigRenderHead () {
    return <div>pig head</div>
  }
  pigRenderBody () {
    return <div>pig body</div>
  }
  pigRenderFoot () {
    return <div>pig foot</div>
  }
  chickenRenderHead() {... }chickenRenderBody() {... }chickenRenderFoot() {... }render () {
    <div>
      <AnimalTemplate
        renderHead={this.pigRenderHead}
        renderBody={this.pigRenderBody}
        renderFoot={this.pigRenderFoot}
      />
      <AnimalTemplate
        renderHead={this.chickenRenderHead}
        renderBody={this.chickenRenderBody}
        renderFoot={this.chickenRenderFoot}
      />
    </div>
    
  }  
}
Copy the code

conclusion

React render props this section gives you a clearer idea of react render props

Three, vUE implementation

With the derivation of the above two steps, it is easy to understand the application of the template method pattern in VUE.

1, children in div with name Joe

// parent.vue
<template>
  <div>
    <div name="tom"></div>
    <div name="joe"> <! Children --> <slot /> </div> </div> </template>Copy the code
// stage.vue <template> <div> <parent> <! Child </div> </parent> </div> </template>Copy the code

2. Implement the OOP completed example again

// AnimalTemplate.vue
<template>
  <div>
    <slot name="head"></slot>
    <slot name="body"></slot>
    <slot name="foot"></slot>
  </div>
</template>
Copy the code
// stage.vue
<template>
  <div>
    <animal-template>
      <div slot="head">pig head</div>
      <div slot="body">pig body</div>
      <div slot="foot">pig foot</div>
    </animal-template>
    <animal-template>
      <div slot="head">chicken head</div>
      <div slot="body">chicken body</div>
      <div slot="foot">chicken foot</div>
    </animal-template>
  </div>
</template>
Copy the code

conclusion

From OOP implementation to React implementation to vUE implementation, it should be easy to understand the application of template method pattern in VUE

Four, do something

Through the introduction of the above we should be to master the theoretical knowledge of the template method mode, with new skills should be applied.

Scenario: List rendering should be a common operation. No matter what kind of list it is, it will have the following characteristics: loading state is displayed when data is requested, prompt is given when there is no data, and render the list when there is data

1. Algorithm encapsulation

According to the theory of template method pattern, we first need to encapsulate the list rendering algorithm:

  • Request data — > Loading
  • Empty data –> Empty data hint
  • Get the data — > Render list
// renderList.vue
<template>
  <div>
    <img v-if="isLoading" src="./loading.gif" />
    <div v-if="isEmpty"> Data is empty </div> <div V-else > <div V-for ="(item, index) in data" :key="index"> <! -- Scope slot in vue --> <slot name="item" :data="item" />
      </div>
    </div>
  </div>
</template>
<script>
  export default {
    name: 'RenderList',
    props: {
      isLoading: Boolean,
      data: Array,
    },
    computed: {
      isEmpty () {
        return this.data.length < 1
      }
    }
  }
</script>
Copy the code

2. Define the implementation of some steps (list items)

// stage.vue
<template>
  <div>
   <render-list :isLoading="isStudentsLoding" :data="students"> <! --> <div slot="item" slot-scope="{ data }"Name: {{data.name}}</div> <div> Age: {{data.age}}</div> </render-list> <render-list :isLoading="isFamilyLoading" :data="family"> <! -- Family member render --> <div slot="item" slot-scope="{ data }"> <! {{data.role}}</span> name: {{ data.name }} </div> </div> </render-list> </div> </template> <script> import RenderList form'./renderList'
  export default {
    data () {
      return {
        isStudentsLoding: false,
        isFamilyLoading: false,
        students: [
          { name: 'aa', age: '18' },
          { name: 'bb', age: 'the' },
          { name: 'cc', age: '120' }
        ],
        family: [
          { name: 'aaaa', role: 'daddy' },
          { name: 'bbbb', role: 'mother' },
          { name: 'cccc', role: 'I' },
        ]
      }
    },
    components: {
      RenderList   
    }
  }
</script>
Copy the code

3. More complicated

When rendering the student list above, I want to show the results of each subject as well. The data structure is as follows:

export default {
  ...
  data () {
    return {
      students: [
	    { name: 'Ming',
	      age: 16, 
	      score: [
	        { course: 'Chinese', value: 86 },
	        { course: 'mathematics', value: 88 }
	      ]
	    },
	    { name: 'xiao li',
	      age: 16, 
	      score: [
	        { course: 'Chinese', value: 90 },
	        { course: 'mathematics', value: 85 }
	      ]
	    }
      ]
    }
  }
  ...
}
Copy the code
Manual implementation in Children?
<render-list :isLoading="isStudentsLoding" :data="students">
 <div slot="item" slot-scope="{ data }"> < div > name: {{data. The name}} < / div > < div > age: {{data. The age}} < / div > <! -- We can get the information for each student and manually render the grade list --> <div v-for="score in data.score" :key="score.course">
     <slot name="score" :data="score" />
   </div>
 </div>
</render-list>
Copy the code
Tweak our list algorithm

The above approach may have served our purpose, but rendering the list was too much for the user to care about, requiring adjustments to our algorithm template

// renderList.vue
<template>
  <div>
    <img v-if="isLoading" src="./loading.gif" />
    <div v-if="isEmpty"> Data is empty </div> <div V-else > <div V-for ="(item, index) in source" :key="index"> <! --> <slot name="item" :data="item"></slot> <! --> <div class="score">
          <div v-for="score in item.score" :key="score.course">
            <slot name="score" :data="score" />
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
Copy the code
// stage.vue
<template>
  <div>
   <render-list :isLoading="isStudentsLoding" :data="students"> <! --> <div slot="item" slot-scope="{ data }"> < div > name: {{data. The name}} < / div > < div > age: {{data. The age}} < / div > < / div > <! <div slot="score" slot-scope="{ data }"> < div > - course: {{data. The course}} < / div > < div > - grade: {{data. Value}} < / div > < / div > < / render - list > < / div > < / template >Copy the code

conclusion

This article shares the concept of the slot design pattern in VUE and shows the application of the template method pattern with the tabletop rendering scenario. The slot API was a bit anxious at the time of writing this article, and V2.6.0 solved the problem pretty well.

Why is the template method pattern the most used design pattern in VUE and React development? Through the above introduction, I believe you have felt the characteristics of the template method pattern: 1, encapsulate a template algorithm 2, the user is responsible for a concrete implementation step React internal packaging ready, now think vue diff algorithm, state changes triggered update mechanism, life cycle, we only need according to the rules of grammar when using framework apis to complete our business logic using them, this is the template method patternCopy the code

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