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
- Iview’s Button component encapsulates the native Button component
- The native Button component is bound with the Click event
- 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
- The Button component of the iView has already bound the native Button click. We need to hijack this binding to prevent shaking
- 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
- Create the Debounce anti-shake function
- Copy the handleClick method in the iView Button component as _handleClick
- Export object, rewrite handleClick method in Methods, for anti – shake control
Using mixins to implement our requirements is simple, but there are many problems
- Need to know the Button source structure
- 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
- Create the Debounce anti-shake function
- Exporting new components
- Render the iView Button
- Button binds the click method after Debounce
HOC’s wrapping nature also poses several problems
- Communication between components is intercepted, such as methods that child components access parent components (this.$parent-methods).
- 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…