Start with a Confirm component and work your way to a pluggable component.

Handle a normal payment process (such as Alipay purchase fund)

  1. Click the Buy button
  2. If risk levels do not match: Confirm
  3. After the user confirms the risk: popup Dialog for payment method selection
  4. After selecting payment method: popup invokes fingerprint verification (Dialog)
  5. If fingerprint validation is turned off: prompt whether to enter password (Dialog)
  6. Popup keyboard for entering password (custom keyboard)
  7. And, of course, crypto overtime
  8. If the password is entered incorrectly, a prompt to modify or retry will appear (Confirm).
  9. . Pop up the keyboard again

About six popovers…

Ground goods (Lite version)

First try implementing it as a normal registered component

Confirm toggles the display with V-Model =”isShow” and receives click events with @onConfirm and onCancel.

Component code

    <template>
        <div v-if="value">
            <slot></slot>
            <div>
                <div @click="cancelHandler">{{cancelTxt}}</div>
                <div @click="confirmHandler">{{confirmTxt}}</div>
            </div>
        </div>
    </template>

    <script>
    export default {
        props: {
            value: {
                type: Boolean,
                default: false,}},data() {
            return {
                content: ' ',
                confirmTxt: ' ',
                cancelTxt: ' ',
            }
        },
        methods: {
            close() {
                this.$emit('input');
            },
            cancelHandler() {
                this.$emit('onCancel');
            },
            confirmHandler() {
                this.$emit('onConfirm');
            }
        }
    }
    </script>
Copy the code

Use the code

    <confirm
        v-model="isConfirmShow"
        @onCancel="onCancel"
        @onConfirm="onConfirm"
    >The content part</confirm>
Copy the code

Use it to fulfill the above requirements.

    openRiskConfirm() {
        this.isRiskConfirmShow = true;
    },
    onRiskCancel() {
        this.isRiskConfirmShow = false;
    },
    onRiskConfirm() {
        // something
        this.openPaymeList();
    },
    openPaymeList() {
        this.isPaymentListShow = ture;
    }
    / /... Bala bala
    / /... Approximately 3*6 = 18 methods are needed to complete the requirement (not counting other request classes)
Copy the code

If that’s okay with you, but:

What if regulation is relaxed and risk checks are no longer needed? Or is there no risk check at the beginning, and all of a sudden regulation has to check risk? Or is it not used on the app, so you don’t need to call the fingerprint? Or add a facial recognition feature?

Code can be a disaster to change, because even if you write the business code, you don’t always remember the flow after a while, and the code doesn’t seem to have any continuity, just one method at a time.

Popular (Lite)

For the business process above, try using the popular popovers.

Component: Change the receiver method location from props to $data

    <template>
        <div>
            <div>{{content}}</div>
            <div>
                <div @click="cancelHandler">{{cancelTxt}}</div>
                <div @click="confirmHandler">{{confirmTxt}}</div>
            </div>
        </div>
    </template>

    <script>
    export default {
        data() {
            return {
                content: ' ',
                confirmTxt: ' ',
                cancelTxt: ' ',
                onConfirm: function() {},
                onCancel: function() {},
            }
        },
        methods: {
            uninstall() {
                this.$destroy(true);
                this.$el.parentNode.removeChild(this.$el);
            },
            cancelHandler() {
                (typeof this.onCancel === 'function') && this.onCancel()
                this.uninstall();
            },
            confirmHandler() {
                (typeof this.onConfirm === 'function') && this.onConfirm()
                this.uninstall();
            }
        }
    }
    </script>
Copy the code

Register to global

    import confirm from './confirm.vue'

    export default {
        install: function(Vue) {
            const Profile = Vue.extend(confirm);
            
            const PortfolioMsg = (options) = > {
                let $ele = document.createElement("div");
                document.body.appendChild($ele);
                new Profile({
                    data() {
                        returnoptions; } }).$mount($ele); }; Vue.prototype.$confirm = PortfolioMsg; }}Copy the code

call

    this.$confirm({
        content: 'content'.confirmTxt: 'sure'.cancelTxt: 'cancel'.onConfirm: (a)= > {
            console.log('sure')},onCancel: (a)= > {
            console.log('cancel')}})Copy the code

What about using it to fulfill the above requirements?

    this.$confirm({
        content: 'Risk Certification'.cancelTxt: 'Let's see.'.confirmTxt: '同意'.onConfirm: (a)= > {
            // something
            this.$dialog({
                content: 'Fingerprint Authentication'.slot: '
      
Fingerprint authentication
.onFinish: (a)= > { // Successful payment? Failure? // something }, onCancel: (a)= > { // something this.$confirm({ content: 'Password authentication'.cancelTxt: 'cancel'.confirmTxt: 'sure'.onConfirm: (a)= > { // something this.$keyboard({ / / a little onFinish: (password) = > { // Password encryption // something if (/* Incorrect password? * /) { / / repeat // This code can be abstracted as a method this.$confirm({ content: 'Password authentication'.cancelTxt: 'cancel'.confirmTxt: 'sure'./ / a little})}}})},onCancel: (a)= > { / / cancel}})}})},onCancel: (a)= > { / / cancel}})Copy the code

Components that do not need to register globally can be implemented by encapsulating a method in methods, making maintenance much easier. But: is there a callback hell? It’s just a little bit easier. Can we optimize it again?

Abstract version

Ajax callback hell could be solved with promises, but could the component callback hell above also use Promises?

import confirm from './confirm.vue'

export default {
    install: function(Vue) {
        const Profile = Vue.extend(confirm);
        
        const PortfolioMsg = (options) = > {
            let $ele = document.createElement("div");
            document.body.appendChild($ele);
            const profile = new Profile({
                data() {
                    return options;
                }
            }).$mount($ele);
            
            return new Promise((resolve, reject) = > {
                profile.$on('onConfirm', resolve)
                profile.$on('onCancel', reject) }) }; Vue.prototype.$confirm = PortfolioMsg; }}Copy the code

Using the

    this.$confirm({
        confirmTxt: 'sure'
    }).then(res= > {
        console.log('Hit OK')
    }).catch(res= > {
        console.log('Hit cancel')})Copy the code

The problem of callback hell is easily solved, readability is very high, adding and deleting logic in the middle is very convenient, and maintenance costs are greatly reduced. It might be better to abstract the concrete code yourself.

Do you have any other encapsulation methods? Please leave a message,

The last

React-hooks UI library: react-hooks UI library

React + Hooks project

Welcome to pay attention to the public number “front-end advanced class” seriously learn the front end, step up together.