项目中封装的组件
按钮
// m-button.vue
<template>
<button
class="m-button"
:type="htmlType"
:disabled="clickStop"
:class="{
...getTheme,
...getSize
}"
@click.prevent="stopReply"
:style="{ ...getStyle }"
>
<slot></slot>
{{text}}
</button>
</template>
<script>
export default {
data() {
return {
clickStop: false,
id: ""
};
},
props: {
htmlType: {
type: String,
default: "button"
},
theme: {
type: String,
default: "skyblue"
},
disabled: {
type: Boolean,
default: false
},
width: {
type: Number,
default: 0
},
height: {
type: Number,
default: 0
},
radius: {
type: Number,
default: 0
},
size: {
type: String,
default: "normal"
},
color: {
type: String,
default: ""
},
ifClickStop: {
type: Boolean,
default: true
}
},
methods: {
stopReply() {
if (this.ifClickStop) {
if (this.clickStop) {
return;
}
this.clickStop = true;
clearTimeout(this.id);
this.$emit("click");
this.id = setTimeout(() => {
this.clickStop = false;
}, 1000);
} else {
this.$emit("click");
}
}
},
computed: {
getTheme() {
let obj = Object.create(null);
if (this.disabled) {
obj["m-button--disabled"] = true;
} else if (this.theme) {
let property = `m-button--theme-${this.theme.toLocaleLowerCase()}`;
obj[property] = true;
}
return obj;
},
getSize() {
let obj = Object.create(null);
if (this.size) {
let property = `m-button--size-${this.size.toLocaleLowerCase()}`;
obj[property] = true;
}
return obj;
},
getStyle() {
let obj = Object.create(null);
let unit = "px";
if (this.width) {
obj.width = this.width + unit;
}
if (this.height) {
obj.height = this.height + unit;
}
if (this.radius) {
obj["border-radius"] = this.radius + unit;
}
if (this.color) {
obj.color = this.color;
}
return obj;
}
}
};
</script>
<style scoped lang="scss">
.m-button {
display: inline-flex;
height: 42px;
font-size: 14px;
color: #fff;
align-items: center;
justify-content: center;
transition: 500ms;
cursor: pointer;
}
.m-button--theme-skyblue {
background: rgba(11, 183, 254, 1);
}
.m-button--theme-skyblue:hover {
background: rgba(11, 165, 254, 1);
}
.m-button--theme-skyblue:active {
background: rgba(27, 188, 254, 1);
}
.m-button--theme-gray {
background: rgba(140, 151, 151, 1);
}
.m-button--theme-lightgray {
color: rgba(102, 102, 102, 1);
background: rgba(201, 202, 202, 1);
}
.m-button--theme-light {
background: rgba(11, 183, 254, 0.2);
border: 1px solid rgba(11, 183, 254, 1);
color: rgba(27, 188, 254, 1);
white-space: nowrap;
transition: 500ms;
&:hover {
border: 1px solid rgba(11, 165, 254, 1);
color: #fff !important;
background: rgba(11, 165, 254, 1);
}
&:active {
border: 1px solid rgba(27, 188, 254, 1);
color: #fff !important;
background: rgba(27, 188, 254, 1);
}
&:focus {
border: 1px solid rgba(27, 188, 254, 1);
color: #fff !important;
background: rgba(27, 188, 254, 1);
}
}
.m-button--disabled,
.m-button:disabled {
background: rgba(140, 151, 151, 1);
cursor: not-allowed;
}
.m-button--size-large {
width: 148px;
}
.m-button--size-middle {
width: 120px;
}
.m-button--size-small {
width: 92px;
}
.m-button--size-smaller {
width: 68px;
height: 32px;
}
</style>
按钮参数说明
props | 类型 | 默认值 | 说明 |
---|---|---|---|
htmlType | String | ‘button’ | 原生type |
theme | String | ‘skyblue’ | [‘skyblue’,‘gray’,‘light’] |
text | String | “ | |
disabled | Boolean | false | 是否禁用 |
width | Number | 0 | 宽度 |
height | Number | 0 | 高度 |
radius | Number | 0 | border-radius |
size | String | ‘normal’ | [‘smaller’,‘small’,‘middle’,‘large’] ‘smaller’: width:68px;height: 32px ‘small’:width:92px; ‘middle’:width: 120px; ‘large’:width: 148px; 默认高度为42px |
color | String | “ | 默认颜色为#fff |
ifClickStop | Boolean | true | 是否禁止重复提交 |
tip.vue
// tip.vue
<template>
<div class="tip" :class="`tip--${type}`">
<span class="tip-icon iconfont" :class="getIcon"></span>
<p class="tip-text">
{{ text }}
<slot></slot>
</p>
</div>
</template>
<script>
export default {
props: {
text: {
type: String,
default: ""
},
type: {
type: String,
default: "error"
}
},
data() {
return {
iconMap: new Map([
["error", "icon-gaojingkongxin"],
["success", "icon-chenggong"]
])
};
},
methods: {
},
computed: {
getIcon() {
let { iconMap, type } = this;
console.log(iconMap,type)
if (iconMap.has(type)) {
return iconMap.get(type);
}
return "";
}
}
};
</script>
<style scoped lang="scss">
.tip {
display: flex;
height: 40px;
padding: 0 11px;
border: 1px solid;
border-radius: 2px;
align-items: center;
justify-content: center;
&--error {
color: #e09e00;
background: #fcf5e5;
}
&--success {
background: rgba(36, 185, 85, 0.1);
color: rgba(36, 185, 85, 1);
}
}
.tip-icon {
margin: -.25ex 7px 0 0;
font-size: 18px;
}
.tip-text {
font-size: 14px;
opacity: 0.8;
}
</style>
tip参数说明
props | 类型 | 默认值 | 说明 |
---|---|---|---|
text | String | “ | — |
type | String | ‘error’ | — |
验证码
// CodeButton.vue
<template>
<m-button
theme="light"
@click.prevent="getCode"
class="codeButton"
:class="{ countDownButton: showcountDownText }"
role="button"
:height="34"
>{{ showcountDownText ? countDownText : text }}</m-button
>
</template>
<script>
import CommonInterface from "@api/common.js";
export default {
data() {
return {
countDownText: "秒后重新发送",
showcountDownText: false,
phone: ""
};
},
mounted: function() {
this.phone = this.tel || this.$store.state.tel;
},
props: {
text: {
type: String,
default: "获取验证码"
},
time: {
type: Number,
default: 60
},
interval: {
type: Number,
default: 1
},
tel: {
type: String,
default: ""
},
templateId: {
type: String,
default: ""
}
},
methods: {
getCode() {
this.sendCode();
this.countDown();
},
countDown() {
if (this.showcountDownText) return;
let id;
let { time, interval } = this;
this.showcountDownText = time > 0;
const downTimeFn = () => {
this.countDownText = time + "秒后重新发送";
if (time <= 0) {
this.showcountDownText = false;
clearTimeout(id);
this.$emit("timeEnd");
return;
}
time -= interval;
id = setTimeout(downTimeFn, interval * 1000);
};
downTimeFn();
},
async sendCode() {
try {
let tel = this.phone;
if (
this.templateId &&
!this.showcountDownText &&
tel &&
/^1[3456789]\d{9}$/.test(tel)
) {
let result = await CommonInterface.sendCode({
phone: this.phone,
templateId: this.templateId
});
let { nonce, curTime, checkSum } = result;
this.$message({
type: "success",
message: result.message,
duration: 5000,
offset: 60
});
this.$emit("codeReturn", { nonce, curTime, checkSum });
}
} catch (e) {
this.$errorMessage(e.message);
}
}
}`
};
</script>
<style scoped lang="scss">
.codeButton {
@extend .btn-lightBlue;
display: flex;
min-width: 106px;
height: 34px;
font-size: 12px;
color: rgba(11, 183, 254, 1);
align-items: center;
justify-content: center;
box-sizing: border-box;
user-select: none;
cursor: pointer;
background: rgba(11, 183, 254, 0.2);
border: 1px solid rgba(11, 183, 254, 1);
border-radius: 2px;
}
.countDownButton {
cursor: default;
}
</style>
验证码参数说明
props | 类型 | 默认值 | 说明 |
---|---|---|---|
text | String | ‘获取验证码’ | 按钮文字 |
time | String | 60 | 倒计时总时间 |
interval | String | 1 | 倒计时每次时间 |
tel | String | ”” | 手机号 |
templateId | String | ”” | — |