Writing Abstract components with Vue

Keywords: Javascript Vue Attribute

Students who have seen the Vue source code can know that components such as < keep alive >, < transition >, < transition group > and so on
The implementation of a component is an object. Note that it has an attribute abstract that is true, indicating that it is an abstract component.

Vue's documents do not mention this concept. In the life cycle of abstract components, we can intercept the events monitored by the package's subcomponents, or do the Dom operations on subcomponents, so that we can encapsulate the functions we need, without caring about the specific implementation of subcomponents.

<!-- more -->

Next, implement a debounce component to intercept the click event of the subcomponent

The core code is as follows:

<script>
import {get, debounce, set} from 'loadsh';

export default {
    name: 'debounce',

    abstract: true, //Mark as abstract component

    render() {
        let vnode = this.$slots.default[0]; // vnode of subcomponent
        if (vnode) {
            let event = get(vnode, `data.on.click`); // click event bound by subcomponent
            if (typeof event === 'function') {
                set(vnode, `data.on.click`, debounce(event, 1000));
            }
        }
        return vnode;
    }
};
</script>

Use

<debounce>
    <button @click="clickHandler">test</button>
</debounce>

As you can see, the click event of the button has been added with the debounce operation.

We can further optimize the debounce component.

<script>
import {get, debounce, set} from '@/utils';

export default {
    name: 'debounce',

    abstract: true, //Mark as abstract component

    props: {
        events: String,
        wait: {
            type: Number,
            default: 0
        },
        options: {
            type: Object,
            default() {
                return {};
            }
        }
    },

    render() {
        let vnode = this.$slots.default[0]; // vnode of subcomponent

        if (vnode && this.events) {
            let eventList = this.events.split(',');
            eventList.forEach(eventName => {
                let event = get(vnode, `data.on[${eventName}]`); // click event bound by subcomponent
                if (typeof event === 'function') {
                    /**
                     * With the debounce operation, the parameters are exactly the same as the debounce of lodash
                     */
                    set(vnode, `data.on[${eventName}]`, debounce(event, this.wait, this.options));
                }
            });
        }
        return vnode;
    }
};
</script>

Use

<debounce events="click" :wait="250" :options="{maxWait: 1000}">
    <button @click="clickHandler">test</button>
</debounce>

We can also debouce the input event of the input box

<debounce events="input" :wait="250" :options="{maxWait: 1000}">
    <input @input="inputandler" placeholder="Enter keywords to search" />
</debounce>

Author: Shellming
Link to this article: https://shellming.com/2019/05/06/vue-absract-components/
Copyright notice: except for the special notice, all articles in this blog adopt CC BY-NC-SA 3.0 License Agreement. Reprint please indicate the source!

Posted by shelbytll on Sat, 16 Nov 2019 08:15:53 -0800