In the project, we often use the component library for rapid development, but in the process, it is inevitable to encounter the transformation and expansion of the component library, how to elegant and simple reconstruction, let’s explore the strange technology of components from a simple demand –Mixins and HOC

Requirements encountered in projects using component libraries

Requirement: to achieve all page button click event anti – shake control

Choose any set of component libraries. In this case, I chose iView for development

The use method of Button component on iView official website is as follows

<template>
    <Button @click="click">Default</Button>
</template>
<script>
    export default {
        methods: {
            click () {
                console.log('yes')
            }
        }
    }
</script>
Copy the code

Button’s source code is also very simple, and here I have removed irrelevant content

<template>
    <button @click="handleClick"></button>
</template>
<script>
    export default {
        name: 'Button',
        components: { Icon },
        props: {
        },
        data () {
        },
        computed: {
        },
        methods: {
            handleClick (event) {
                this.$emit('click', event); }},mounted() {}}; </script>Copy the code

The following information can be obtained from the source code

  1. Iview’s Button component encapsulates the native Button component
  2. The native Button component is bound with the Click event
  3. When the Click event is emitted, the click event is emitted to the component

How to implement requirements

Taking a look at our requirements for anti-shake control of all page button clicks, here are a few key points

  1. The Button component of the iView has already bound the native Button click. We need to hijack this binding to prevent shaking
  2. Anti – shock control, the anti – shock function, there are many examples on the web, easy to implement

So the challenge for requirements is, how do you hijack click events? There are two options here

Mixins

1. What is a Mixin

Mixins are covered in great detail in the official Vue documentation for those who are not familiar with them, and can be understood in one sentence: components that merge components

The official introduction

Let me draw it as a graph

2. How to solve the need

Direct source code

// The buffeting functionfunction debounce (func, delay, context, event) {
  clearTimeout(func.timer)
  func.timer = setTimeout(function() {func.call(context, event)}, delay)} // copy the click method in iViewfunction _handleClick (event) {
  this.$emit('click'Event), const openInNewWindow = event. CtrlKey | | event. MetaKey enclosing handleCheckClick (event, openInNewWindow)} / / export new componentsexportThe default {props: {}, mixins: [Vue.options.com ponents. Button], / / iview Button componentdata () {
    return{}},mounted () {
    console.log('mixins succeed')
  },
  methods: {
    handleClick (event) {
      let that = this
      console.log('debounce')
      debounce(_handleClickLink, 300, that, event)
    }
  }
}

Copy the code

Principle 3.

The mixins principle is easy to understand, the source code above we do these operations, to achieve the ivew Button component, hijacking the click event

  1. Create the Debounce anti-shake function
  2. Copy the handleClick method in the iView Button component as _handleClick
  3. Export object, rewrite handleClick method in Methods, for anti – shake control

Using mixins to implement our requirements is simple, but there are many problems

  1. Need to know the Button source structure
  2. Implicit dependencies are introduced, which can be difficult to understand if mixins are nested

So is there a better way?

HOC

1. What is HOC?

High-order components are high-order functions. React and Vue both prove one thing: a function is a component. So the statement that a component is a function is true, and the higher-order component is naturally a higher-order function, that is, a function that returns a function

HOC detailed introduction and implementation, this article explores Vue higher-order components have detailed introduction, understood in one sentence, namely the component of the wrapped component

Let me draw it as a graph

2. How to solve the need

Direct source code

// The buffeting functionfunction debounce (func, delay, context, event) {
  clearTimeout(func.timer)
  func.timer = setTimeout(function() {func.call(context, event)}, delay)} // Export the new componentexport default {
  props: {},
  name: 'ButtonHoc'.data () {
    return{}},mounted () {
    console.log('HOC succeed')
  },
  methods: {
    handleClickLink (event) {
      let that = this
      console.log('debounce')
      // that.$listeners.click is the click function debounce(that is bound to the new component.$listeners.click, 300, that, event)
    }
  },
  render (h) {
    const slots = Object.keys(this.$slots)
      .reduce((arr, key) => arr.concat(this.$slots[key]), [])
      .map(vnode => {
        vnode.context = this._self
        return vnode
      })
    return h('Button', {on: {click: this.handleClickLink // new component binding click event}, props: this.$props// Passthrough scopedSlots scopedSlots: this.$scopedSlots,
      attrs: this.$attrs
    }, slots)
  }
}

Copy the code

Principle 3.

HOC is characterized by its wrapping, the above source code we do these operations, to achieve a wrapped iView Button component, hijacking the click event

  1. Create the Debounce anti-shake function
  2. Exporting new components
  3. Render the iView Button
  4. Button binds the click method after Debounce

HOC’s wrapping nature also poses several problems

  1. Communication between components is intercepted, such as methods that child components access parent components (this.$parent-methods).
  2. Vue does not officially recommend using HOC 🙁

conclusion

Both Mixins and HOC fulfill this simple requirement, and hopefully you can understand both techniques and solve problems in your project

Source: github.com/warpcgd/mix…

Demo: warpcgd. Making. IO/mixinAndHoc…