涉及到的知识点其实就是父子组件之间属性和方法的使用
第一步:在components目录下新建一个子组件(field.vue)
<template>
<div
class="cell-wrapper"
:class="showVerify ? 'include-verify flex-base' : ''"
>
<div
class="cell-item flex-base"
:style="{backgroundColor: cellBgColor}"
>
<div
class="left"
:class="label !== undefined && label !== '' ? 'flex-label' : ''"
>
<label>{{ label }}</label>
<i class="van-icon" :class="`van-icon-${leftIcon}`"></i>
</div>
<div class="right flex-base">
<input
v-if="type === undefined"
ref="input"
type="text"
v-on:value="value"
:placeholder="placeHolder"
:style="{backgroundColor: cellBgColor === undefined ? inputBgColor : cellBgColor}"
@input="updateValue($event.target.value)"
@focus="onFocus"
@blur="onBlur"
@click="clickInput"
>
<select
v-if="type === 'select'"
@change="changeSelect($event.target.value)"
>
<option value="">请选择</option>
<option
v-for="(option, index) in options"
:key="index"
:value="option.value"
>
{{ option.label }}
</option>
</select>
<i
class="van-icon van-icon-clear"
v-if="!success && showClear"
@click="clearValue"
/>
<i
class="van-icon van-icon-passed"
v-if="success"
/>
<p class="error">{{ errorMsg }}</p>
</div>
</div>
<div
v-if="showVerify"
class="getCode"
@click="getVerifyCode"
:class="showCodeBtn ? '' : 'disabled-get'"
>
{{ showCodeBtn ? '获取验证码' : `${authTime}s后重试` }}
</div>
</div>
</template>
<script>
export default {
name: 'formCell',
props: {
type: {},
label: {},
leftIcon: {},
clearIcon: {}, // 清除图标
successIcon: {}, // 校验成功时显示的图标
placeHolder: {}, // input的placeholder
errorMsg: {}, // 显示错误信息
inputBgColor: { // input输入框的背景
type: String,
default: '#F5F5F5'
},
cellBgColor: {}, // 整行背景
success: { // 校验成功
type: Boolean,
default: false
},
showVerify: {}, // 显示验证码
showCodeBtn: {}, // 显示获取验证码按钮
authTime: {},
options: { // 下拉选项
type: Array
}
},
data () {
return {
showClear: false,
inputRef: '',
value: ''
}
},
methods: {
setValue (val) {
this.$emit('input', val);
},
// 更新选择项
changeSelect (val) {
this.$emit('change', val, this.label);
},
// 更新input的value值
updateValue (val) {
if (val) {
this.showClear = true;
} else {
this.showClear = false;
}
this.setValue(val);
},
// 点击input无延迟聚焦
clickInput () {
this.inputRef.focus();
},
// 聚焦事件
onFocus () {
this.$emit('watchFocus');
},
// 失焦事件
onBlur () {
this.$emit('watchBlur');
},
// 清空input的value值
clearValue () {
this.inputRef.value = '';
this.inputRef.focus();
this.updateValue('');
},
getVerifyCode () {
this.$emit('getVerifyCode')
}
},
created () {
let _this = this;
this.$nextTick(() => {
_this.inputRef = this.$refs.input;
})
}
};
</script>
<style scoped lang="scss" type="text/scss">
.getCode{
flex: 1;
font-size: 30px;
color: #FFF;
text-align: center;
background: $theme;
padding: 25px 5px;
margin-left: 25px;
border-radius: 20px;
}
.disabled-get{
background: #8d8d8d;
}
.cell{
&-wrapper{
position: relative;
padding: 15px 20px 30px;
}
&-item{
padding: 15px 20px;
.flex-label{
flex: .2;
text-align: right;
}
.left{
margin-right: 20px;
.van-icon{
font-size: 45px;
color: $theme;
}
}
.right{
position: relative;
flex: 1;
input{
width: 100%;
height: 60px;
text-indent: 15px;
}
select{
appearance:none;
-moz-appearance:none;
-webkit-appearance:none;
width: 100%;
height: 80px;
border: none;
outline: none;
color: #888;
font-size: 30px;
text-indent: 15px;
background: #F5F5F5;
&::after{
content: '';
width: 50px;
height: 50px;
background: #000;
position: absolute;
right: 0;
}
}
::-webkit-input-placeholder { /* WebKit browsers */
color: #888;
font-size: 28px;
}
:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
color: #888;
font-size: 28px;
}
::-moz-placeholder { /* Mozilla Firefox 19+ */
color: #888;
font-size: 28px;
}
:-ms-input-placeholder { /* Internet Explorer 10+ */
color: #888;
font-size: 28px;
}
.van-icon{
position: absolute;
top: 20px;
right: 10px;
&-clear{
color: $theme;
}
&-passed{
color: #1bbb00;
}
}
.error{
position: absolute;
bottom: -50px;
font-size: 25px;
color: $theme;
margin: 0;
}
}
}
}
.include-verify {
.cell-item{
flex: 2;
}
}
</style>
第二步、父组件使用field组件
<template>
<div class="verified">
<new-layout centerColor="#FFF">
<template slot="center">
<div class="field-group">
<form-field
leftIcon="yonghu"
placeHolder="请输入您的姓名"
cellBgColor="#F5F5F5"
v-model="formData.name.value"
:errorMsg="formData.name.err"
:success="formData.name.success"
@watchFocus="watchInputFocus('name')"
@watchBlur="watchInputBlur(formData.name.value, 'name')"
/>
<form-field
leftIcon="Id"
placeHolder="请输入您的身份证号"
cellBgColor="#F5F5F5"
v-model="formData.idCard.value"
:errorMsg="formData.idCard.err"
:success="formData.idCard.success"
@watchFocus="watchInputFocus('id')"
@watchBlur="watchInputBlur(formData.idCard.value, 'id')"
/>
<form-field
leftIcon="shouji1"
placeHolder="请输入您的手机号"
cellBgColor="#F5F5F5"
v-model="formData.phone.value"
:errorMsg="formData.phone.err"
:success="formData.phone.success"
@watchFocus="watchInputFocus('phone')"
@watchBlur="watchInputBlur(formData.phone.value, 'phone')"
/>
<form-field
leftIcon="queren"
placeHolder="请输入手机验证码"
cellBgColor="#F5F5F5"
v-model="formData.verifyCode.value"
:errorMsg="formData.verifyCode.err"
:success="formData.verifyCode.success"
:showVerify="showVerify"
:showCodeBtn="showCodeBtn"
:authTime="authTime"
@watchFocus="watchInputFocus('verify')"
@watchBlur="watchInputBlur(formData.verifyCode.value, 'verify')"
@getVerifyCode="getVerifyCode"
/>
<div
class="commit"
@click="commitData"
:class="isPassAll ? '' : 'disabled'"
>
确认提交
</div>
</div>
</template>
</new-layout>
</div>
</template>
<style lang="scss" scoped>
.field-group{
padding-top: 20px;
}
.commit{
width: 70%;
padding: 25px;
margin: 70px auto 30px;
border-radius: 20px;
display: flex;
justify-content: center;
align-items: center;
background: $theme;
color: #FFF;
}
.disabled{
background: #8d8d8d;
}
</style>
<script>
import infoCell from '@/components/addresses/infoCell';
import { _debounce } from '../../../mixins/utils';
export default {
name: '',
components: {
infoCell
},
data() {
return {
showVerify: true,
showCodeBtn: true,
clearAble: true, // input清除控件
authTime : 0,
// 表单数据
formData: {
name: {
value: '',
err: '',
success: false
},
idCard: {
value: '',
err: '',
success: false
},
phone: {
value: '',
err: '',
success: false
},
verifyCode: {
value: '',
err: '',
success: false
}
}
};
},
computed: {
isPassAll () {
if (
this.formData.name.success && this.formData.idCard.success &&
this.formData.phone.success && this.formData.verifyCode.success
) {
return true
} else {
return false
}
}
},
created() {
},
methods: {
// 重置错误信息
setErrMsg (value) {
return value ? true : false;
},
clearValue () {
},
// 监听input组件聚焦事件
watchInputFocus (flag) {
switch (flag) {
case 'name':
this.formData.name.success = false;
break;
case 'id':
this.formData.idCard.success = false;
break;
case 'phone':
this.formData.phone.success = false;
break;
case 'verify':
this.formData.verifyCode.success = false;
break;
default:
break;
}
},
// 监听input组件失焦事件
watchInputBlur (value, flag) {
switch (flag) {
case 'name':
this.formData.name.err = this.setErrMsg(value) ? '' : '请输入姓名';
this.formData.name.success = this.setErrMsg(value) ? true : false;
break;
case 'id':
this.formData.idCard.err = '';
let idEmpty = this.setErrMsg(value);
let isId = this.regIdCard(value);
if (idEmpty) {
if (!isId) {
this.formData.idCard.err = '身份证号码格式错误'
}
} else {
this.formData.idCard.err = '身份证号不能为空'
}
this.formData.idCard.success = idEmpty && isId ? true : false;
break;
case 'phone':
let phoneEmpty = this.setErrMsg(value);
let isPhone = this.regPhoneNumber(value);
this.formData.phone.err = '';
if (phoneEmpty) {
if (!isPhone) {
this.formData.phone.err = '手机号格式错误';
}
} else {
this.formData.phone.err = '手机号不能为空';
}
this.formData.phone.success = phoneEmpty && isPhone ? true : false;
break;
case 'verify':
this.formData.verifyCode.err = '';
this.formData.verifyCode.err = this.setErrMsg(value) ? '' : '请输入验证码';
this.formData.verifyCode.success = this.setErrMsg(value) ? true : false;
break;
default:
break;
}
},
/**
* 获取验证码
* 60s倒计时
*/
getVerifyCode () {
if (this.showCodeBtn) {
this.showCodeBtn = false;
this.authTime = 59;
let authTimer = setInterval(() => {
this.authTime--;
if (this.authTime <= 0) {
this.showCodeBtn = true;
clearInterval(authTimer);
}
}, 1000);
}
},
// 提交
commitData: _debounce(function() {
if (this.isPassAll) {
console.log('提交表单数据!');
}
}, 800),
}
};
</script>