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 may be a little different from the previous articles, the previous few to achieve our purpose had to create a lot of objects (components), but the main character of this article is to let us reduce the object-share model. Definition (from the web) :

The share pattern uses sharing techniques to reuse the same or similar objects. This means that code sharing implements the same or similar objects.

Usage Scenarios (from Baidu Baike) :

If an application uses a large number of objects, and these objects cause a large storage overhead, you can consider whether to use the free element pattern.

A, requirements,

Screenshot from iView official documentation (Message component)

The Message component is familiar to you. I wonder if you have implemented it yourself

Second, demand analysis

The Message component has the following characteristics:

  • Same interaction
  • There are three types:success,warning,error, corresponding to three different page effects: prompt icon, background style, font style
  • Receive a prompt text

Can know:

Interaction mode – pop, hide, owned by shared objects

Prompt icon, background style, font style provide interface configurable

Use API unity

Iii. Design and implementation

This.$message.success (), this.$message.warning (), this.$message.error () so we need to extend vue prototype as a vue plugin

/ / Message. Js pseudo codeexportDefault {install (Vue) {// Extend Vue's 'prototype' Vue. Prototype.$MessageConst Dialog = new Vue({... }) document.body.appendChild(Dialog.$el}, warning (text) {// new a new component object const Dialog = new Vue({... }) document.body.appendChild(Dialog.$el}, error (text) {// new a new component object const Dialog = new Vue({... }) document.body.appendChild(Dialog.$el)}}}}Copy the code

As shown in the example above, every time the Message component is used, a new Dialog is created. Now we use the idea of the share mode to reduce the number of component objects

/ / Message. Js pseudo codeexportDefault {install (Vue) {// Instantiate a Dialog component object when using Vue. Use (Message) const Dialog = new Vue({data () {
        return {
          icon: ' ',
          fontStyle: ' ',
          backgroundStyle: ' ',
          text: ' '}}... }) // Extend Vue's 'prototype' Vue. Prototype.$Message// Change the value of data.xx to dialog. icon = successIcon dialog. fontStyle = successFontStyle Dialog.backgroundStyle = successBackgroundStyle dialog. text = text // Get the latest DOM of Dialog to add to the body tag document.body.appendChild(Dialog.$el}, warning (text) {// same as above... document.body.appendChild(Dialog.$el}, error (text) { document.body.appendChild(Dialog.$el)}}}}Copy the code

Four, the results

They say things are results-oriented. Now look at the results of our design

Dialogs are only new once during project initialization. Each time the Message component is used to retrieve the component DOM by changing the Dialog state, it is easy to see that the cost of a new component is much higher than the cost of updating a component

The disadvantage compared to the normal implementation is that new Dialog() is executed even when unused and takes up memory

V. Complete implementation (example)

If there is a bug, please feel free to write

import './index.scss'

let zIndex = 2001;

export default {
  install (Vue) {
    const Dialog = new Vue({
      data () {
        return {
          text: 'Here's a hint.',
          icon: 'icon-waiting',
          iconColor: '#308AFE',
          background: '#ddd'
        }
      },
      render (h) {
        zIndex++
        const selfStyle = {
          background: this.background,
          zIndex
        }
        return h('div',
          {
            class: 'm-message',
            style: selfStyle
          },
          [
            h('i', {
              style: {marginRight: '8px', color: this.iconColor},
              class: `iconfont ${this.icon}`
            }),
            this.text
          ]
        )
      }
    }).$mount(a)function appendDialog(message, icon, iconColor, bgColor, time = 3) {
      Dialog.text = message
      Dialog.icon = icon
      Dialog.iconColor = iconColor
      Dialog.background = bgColor
      let timer = ' '
      let element = document.createElement('div')
      Dialog.$nextTick(() => {
        element = Dialog.$el.cloneNode(true)
        document.body.appendChild(element)
      })
      if(time > 0) {
        timer = setTimeout(() => {
            element.classList.add('outer')
            setTimeout(() => {
              document.body.removeChild(element)
            }, 500);
            clearTimeout(timer)
        }, time * 1000);
      }
    }

    Vue.prototype.$message = {
      tips (message, time) {
        appendDialog(message, 'icon-waiting'.'#308AFE'.'#ADD8F7', time)
      },
      warning(message, time) {
        appendDialog(message, 'icon-warn'.'#FFAF0D'.'#FCCCA7', time)
      },
      success(message, time) {
        appendDialog(message, 'icon-success'.'#36B37E'.'#A7E1C4', time)
      },
      error(message, time) {
        appendDialog(message, 'icon-error'.'#E95B5B'.'#FFF4F4', time)
      },
      destory() {
        document.querySelectorAll('.m-message').forEach(ele => ele.remove())
      }
    }
  }
}
Copy the code

Six, summarized

Think back to a scenario that is often used when talking about the Meta pattern

There are 50 suits for men and 50 suits for women. Now what are we going to do to take pictures of these suits? Rational approach: New one male model and one female model shoot one set and then shoot another set (expose a interface for changing clothes), it is not bad, mainly to save money (reduce the object from 100 to 2)Copy the code

Those who are familiar with the design pattern may think this scene is not very good. I agree with your opinion, but I think it is acceptable to use it to learn the yuan pattern. A concrete implementation of the Message component does not reject or recommend the approach of this article.

Update: Elemnet-UI’s MessageBox component is found to be a similar thought portal


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