标签:mit 现在 dial alt boolean inpu script 点击 如何
从一个 Confirm 组件开始,一步步写一个可插拔式的组件。
处理一个正常的支付流程(比如支付宝购买基金)
大约6个弹窗...
首先尝试以一个平常的注册组件实现
Confirm 通过 v-model="isShow" 切换展示,通过 @onConfirm 和 onCancel 接收点击事件。
组件代码
    <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>使用代码
    <confirm
        v-model="isConfirmShow"
        @onCancel="onCancel"
        @onConfirm="onConfirm"
    >内容部分</confirm>那么用它来完成上面的需求吧。
    openRiskConfirm() {
        this.isRiskConfirmShow = true;
    },
    onRiskCancel() {
        this.isRiskConfirmShow = false;
    },
    onRiskConfirm() {
        // something
        this.openPaymeList();
    },
    openPaymeList() {
        this.isPaymentListShow = ture;
    }
    // ... 巴拉巴拉
    // ... 大约需要 3*6 = 18 个方法才能完成需求(其他请求类的还不算)如果你能接受,但是:
那么万一监管放松了,不需要校验风险了呢?或者一开始没有校验风险,监管突然要校验风险了呢?又或者不在 app 上使用,不用调用指纹呢?又或者要添加一个 人脸识别功能了呢?
代码改起来会是一个灾难,因为就算业务代码是你写的,你一段时间后也不一定能记得流程,而且,代码看起来没有任何的连续性,只能一个个方法看。
针对上面的业务流程,尝试使用现在比较流行的的弹窗。
组件:更改接收方法位置,从 props 放到 $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>注册到全局
    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() {
                        return options;
                    }
                }).$mount($ele);
            };
            Vue.prototype.$confirm = PortfolioMsg;
        }
    }调用
    this.$confirm({
        content: '内容',
        confirmTxt: '确定',
        cancelTxt: '取消',
        onConfirm: () => {
            console.log('确定')
        },
        onCancel: () => {
            console.log('取消')
        }
    })哪啊么用它完成上面的需求会如何?
    this.$confirm({
        content: '风险认证',
        cancelTxt: '再看看',
        confirmTxt: '同意',
        onConfirm: () => {
            // something
            this.$dialog({
                content: '指纹认证',
                slot: `<div>指纹认证</div>`,
                onFinish: () => {
                    // 支付 成功? 失败?
                    // something
                },
                onCancel: () => {
                    // something
                    this.$confirm({
                        content: '密码认证',
                        cancelTxt: '取消',
                        confirmTxt: '确定',
                        onConfirm: () => {
                            // something
                            this.$keyboard({
                                // 略
                                onFinish: (password) => {
                                    // 密码加密
                                    // something
                                    if (/* 密码错误? */) {
                                        // 重复了
                                        // 这个代码就可以抽象成一个方法
                                        this.$confirm({
                                            content: '密码认证',
                                            cancelTxt: '取消',
                                            confirmTxt: '确定',
                                            // 略
                                        })
                                    }
                                }
                            })
                        },
                        onCancel: () => {
                            // 取消
                        }
                    })
                }
            })
        },
        onCancel: () => {
            // 取消
        }
    })这样看起来确实清晰了很多,代码量也少了很多,不需要注册全局的组件可以通过在 methods 中封装一个方法实现,维护起来也方便了很多。但是:回调地狱有木有?也只是稍微轻松一点,可不可以再优化一下呢?
ajax 的回调地狱是通过 Promise 实现的,那么上面的组件回调地狱是不是也可以通过 Promise 实现呢?
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;
    }
}使用一下
    this.$confirm({
        confirmTxt: '确定'
    }).then(res => {
        console.log('点击了确定')
    }).catch(res => {
        console.log('点击了取消')
    })那么回调地狱的问题很轻松的就解决了,可读性很高,中间添加删除逻辑也变的特别方便,维护起来成本大大的降低了。具体代码自己抽象一遍或许更好哦。
大家其他的封装方法吗?请留言哈
译者写了一个 React + Hooks 的 UI 库,方便大家学习和使用,
欢迎关注公众号「前端进阶课」认真学前端,一起进阶。
标签:mit 现在 dial alt boolean inpu script 点击 如何
原文地址:https://www.cnblogs.com/zhongmeizhi/p/12172938.html