button组件封装 入门学习-5

60 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

loading加载按钮

利用 :loading='true'来控制显隐

<template>
    <div>
        <a-button loading  min-width="100px">默认按钮</a-button>
        <a-button  type="primary" block perfix="upload" border round disabled size="small">蓝色按钮</a-button>
        <a-button type="success"  suffix="upload2" size="mini">绿色按钮</a-button>
        <a-button type="wraning" min-width="160px">橙色按钮</a-button>
        <a-button type="danger" min-width="160px" border>红色按钮红色按钮红色按钮红色按钮</a-button>
    </div>
</template>
//组件
<template>
        <button  
            class="a-button"
            :disabled="disabled" 
            :class="[theme, isBorder, isRound,isSize]"
            :style="[minWidthCss,blockCss]"
        >
            <span>
                <!-- 前缀 -->
                <i v-if="loading" class="iconfont icon-prefix icon-loading"></i>
                <i v-if="iconPerfix" class="iconfont icon-prefix" :class="iconPerfix"></i>
                <slot />
                <!-- 后缀 -->
                <i v-if="iconSuffix" class="iconfont icon-suffix" :class="iconSuffix"></i>
            </span>
        </button>
</template>
<script>
export default {
    name: "AButton",
    props: {
        loading: Boolean //默认是false
    },
};
</script>

再设置一个加载的动画

//加载动画
.icon-loading {
    animation: loding 1s infinite linear ;
}
@keyframes loding{
    0% {
        transform: rotate(0deg)
    }
    100% {
        transform: rotate(1turn);

    }
}

7b3a00522394a83de3b549e7b4b388f.png

loading点击加载,举一个小例子

点击按钮开始 loading加载,3秒后停止加载

//子组件
<template>
        <button  
            @click="change"
            class="a-button"
            :disabled="disabled" 
            :class="[theme, isBorder, isRound,isSize]"
            :style="[minWidthCss,blockCss]"
        >
            <span>
                <!-- 前缀 -->
                <i v-if="loading" class="iconfont icon-prefix icon-loading"></i>
                <i v-if="iconPerfix" class="iconfont icon-prefix" :class="iconPerfix"></i>
                <slot />
                <!-- 后缀 -->
                <i v-if="iconSuffix" class="iconfont icon-suffix" :class="iconSuffix"></i>
            </span>
        </button>
</template>
    methods: {
        change() {
            this.$emit('click')
        }
    }
//父组件
<template>
    <div>
        <a-button :loading="flag"  min-width="100px" @click="handlerChange">默认按钮</a-button>
    
    </div>
</template>
    methods: {
        handlerChange() {
            this.flag = true
            setTimeout(() => {
            this.flag = false
            },3000)
        }
    }

loading异步加载

这里我们用Promise的方法来异步加载,通过resolve, reject来执行.then 和 .catch,平常我们工作中调借口也是如此;这里我们重新定义一个变量load

首先我们定义一个异步函数asyncFunction

 <a-button :loading="flag" :before-change="asyncFunction"  min-width="100px" >默认按钮</a-button>
         asyncFunction() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve()
            },3000)
            })
        },

子组件中我们接受并判断他是不是函数然后执行.then()

    data() {
    return {
        load: false
    };
    },
 props: {
        beforeChange: Function,
    },
  methods: {
        change() {
            if(typeof this.beforeChange === 'function') {
                    this.load = true
                this.beforeChange().then(response => {
                    this.load = false
                }).catch(() => {
                    this.load = false
                })
            }
            this.$emit('click')
        }
    }

load来控制显隐

   <i v-if="loading || load" class="iconfont icon-prefix icon-loading"></i>

附完整代码

<template>
    <div>
        <a-button :loading="flag" :before-change="asyncFunction"  min-width="100px" >默认按钮</a-button>
        <a-button  type="primary" block perfix="upload" border round disabled size="small">蓝色按钮</a-button>
        <a-button type="success"  suffix="upload2" size="mini">绿色按钮</a-button>
        <a-button type="wraning" min-width="160px">橙色按钮</a-button>
        <a-button type="danger" min-width="160px" border>红色按钮红色按钮红色按钮红色按钮</a-button>
    </div>
</template>
<script>
export default {
    name: 'Home',
    components: {
        'a-button': () => import('@/components/button')
    },
    data() {
        return {
            flag: false
        }
    },
    methods: {
        asyncFunction() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve()
            },3000)
            })
        },
    }
}
</script>
<template>
    
        <button  
            @click="change"
            class="a-button"
            :disabled="disabled || loading || load" 
            :class="[theme, isBorder, isRound,isSize]"
            :style="[minWidthCss,blockCss]"
        >
            <span>
                <!-- 前缀 -->
                <i v-if="loading || load" class="iconfont icon-prefix icon-loading"></i>
                <i v-if="iconPerfix" class="iconfont icon-prefix" :class="iconPerfix"></i>
                <slot />
                <!-- 后缀 -->
                <i v-if="iconSuffix" class="iconfont icon-suffix" :class="iconSuffix"></i>
            </span>
        </button>
        
</template>
<script>
export default {
    name: "AButton",
    props: {
        type: {
            type: String,
            default: ''
        },
        size: {
            type: String,
            default: ''
        },
        minWidth: {
            type: String,
            default: ''
        },
        perfix: {
            type: String,
            default: ''
        },
        suffix: {
            type: String,
            default: ''
        },
        border: Boolean, //默认是false
        round: Boolean, //默认是false
        disabled: Boolean, //默认是false
        block: Boolean, //默认是false
        loading: Boolean, //默认是false
        beforeChange: Function,
    },
    computed: {
        //主题
        theme() {
            return this.type ? `a-button-${this.type}` : ''
        },
        isSize() {
            return this.size ? `a-button-${this.size}` : ''
        },
        isBorder() {
            return this.border ? `is-border` : ''
        },
        isRound() {
            return this.round ? `is-round` : ''
        },
        minWidthCss() {
            if(!this.minWidth) { return ""}
            return { 'min-width' : this.minWidth }
        },
        iconPerfix() {
            return this.perfix ? `icon-${this.perfix}` : ''
        },
        iconSuffix() {
            return this.suffix ? `icon-${this.suffix}` : ''
        },   
        blockCss() {
            return this.block ? { 'display': 'block '} : ''
        }
    },
    data() {
    return {
        load: false
    };
    },
    methods: {
        change() {
            if(typeof this.beforeChange === 'function') {
                    this.load = true
                this.beforeChange().then(response => {
                    this.load = false
                }).catch(() => {
                    this.load = false
                })
            }
            this.$emit('click')
        }
    }
};
</script>
<style lang="less" scoped>
button {
    margin: 15px;
}
.a-button {
    border-width: 1px;
    border-style: solid;
    border-color: #dcdfdc;
    border-radius: 4px;
    background-color: #fff;
    font-size: 14px;
    color: #606266;
    height: 40px;
    span {
        display: flex;
        align-items: center;
        justify-content: center;
    }
}
// i { width: 14px; height: 14px;}
.icon-prefix { margin-right: 10px; }
.icon-suffix { margin-left: 10px; }
.a-button-medium {
    height: 36px;
}
.a-button-small {
    padding: 0 15px;
    height: 32px;
    font-size: 12px;
}
.a-button-mini {
    padding: 0 15px;
    height: 28px;
    font-size: 12px;
}
.a-button[disabled] {
    opacity: .5;
    cursor: not-allowed;
}
.a-button-primary {
    background-color: #409eff;
    border-color: #409eff;
    color: #fff;
    &.is-border {
        background-color: transparent;
        color: #409eff;
    }
}
.a-button-success {
    background-color: #00d100;
    border-color: #00d100;
    color: #fff;
    &.is-border {
        background-color: transparent;
        color: #00d100;
    }
}
.a-button-wraning {
    background-color: #e6a23c;
    border-color: #e6a23c;
    color: #fff;
    &.is-border {
        background-color: transparent;
        color: #e6a23c;
    }
}
.a-button-danger {
    background-color: #f56c6c;
    border-color: #f56c6c;
    color: #fff;
    &.is-border {
        background-color: transparent;
        color: #f56c6c;
    }
}
.is-round { border-radius: 30px;}
//加载动画
.icon-loading {
    animation: loding 1s infinite linear ;
}
@keyframes loding{
    0% {
        transform: rotate(0deg)
    }
    100% {
        transform: rotate(1turn);

    }
}
</style>