赞
踩
系列文章的所有文章的目录
【Taro开发】-简易的checkBoxGroup组件(九)
【Taro开发】-宣传海报,实现canvas实现圆角画布/图片拼接二维码并保存(十一)
【Taro开发】-小程序自动打包上传并生成预览二维码(十三)
【Taro开发】-全局自定义导航栏适配消息通知框位置及其他问题(十四)
基于Taro的微信小程序开发,主要组件库为Taro-ui。
formItem组件需满足前后缀,是否必填,校验提示。
form组件需能在submit时返回是否全部通过校验。
由于taro-ui组件库无相关组件/不满足需求,因此进行封装重写。
提示:以下是本篇文章正文内容,下面案例可供参考
//utils/util
import Schema from 'async-validator';
export const onValidateField = (value, rules) => {
const validator = new Schema(rules);
return new Promise((resolve) => {
validator.validate(value, (errors, fields) => {
if (errors) {
resolve(errors);
} else {
const errMsg = Object.keys(rules).map((key) => {
return {
field: key,
message: undefined,
};
});
resolve(errMsg);
}
});
});
};
/* eslint-disable no-undef */
import React, { Component } from "react";
import { View, Text, Switch, Form, Button } from "@tarojs/components";
import Taro, { getCurrentInstance } from "@tarojs/taro";
import { AtIcon } from "taro-ui";
import "./index.scss";
import { onValidateField } from "@/utils/util";
class FormItem extends Component {
constructor() {
super();
this.state = {
errMsg: []
};
}
check = async (value, rule) => {
const errors = await onValidateField(value, rule);
this.setState({ errMsg: errors });
};
renderChildren(props) {
//遍历所有子组件
return React.Children.map(props.children, child => {
if (!props.children?.length)
return React.cloneElement(child, {
//把父组件的props.name赋值给每个子组件
name: props.name,
onChange: val => {
if (val !== child?.props.value) {
let checkName = props.name;
props.rules &&
this.check({ [checkName]: val }, { [checkName]: props.rules });
child.props.onChange && child.props.onChange(val);
}
}
});
else return child;
});
}
checkRules(rules) {
// 检查为必填项
if (Array.isArray(rules)) {
for (let i = 0; i < rules.length; i++) {
if (rules[i].required) {
return true;
}
}
} else {
return false;
}
}
render() {
const { errMsg } = this.state;
const {
prefix,
suffix,
title,
enter,
enterCallBack,
hasLine,
rules
} = this.props;
return (
<View className="trace-rowAlignCenter form">
{prefix}
<Text className={this.checkRules(rules) ? "label necessary" : "label"}>
{title}
</Text>
<View
className={
hasLine ? "trace-rowAlignCenter hasline" : "trace-rowAlignCenter"
}
style={{ flex: 1 }}
onClick={() => enterCallBack && enterCallBack()}
>
<View style={{ flex: 1 }}>{this.renderChildren(this.props)}</View>
{suffix ||
(enter ? (
<AtIcon size={24)} value="chevron-right" color="#999" />
) : (
<AtIcon
className="perch"
size={24}
value="chevron-right"
color="#999"
/>
))}
</View>
{errMsg?.length > 0 && errMsg[0].message && (
<Text className="formTip">{errMsg[0].message}</Text>
)}
</View>
);
}
}
export default FormItem;
@import "@/styles/variables.scss";
.form {
position: relative;
display: flex;
align-items: center;
padding-left: 32px;
height: 112px;
background-color: $color-white;
.at-icon {
// 前缀图标
margin-right: 24px;
}
.necessary {
// 是否显示红*
&:after {
content: "*";
color: $color-red;
}
}
.label {
// 标题名称
font-size: 32px;
color: $color-black;
}
.formTip {
// 提示红字
color: $color-red;
position: absolute;
right: 66px;
bottom: 5px;
}
.hasline {
border-bottom: 1px solid #f0f0f0;
}
.trace-rowAlignCenter {
height: 100%;
.at-input {
background-color: $color-white;
&:after {
display: none;
}
.at-input__input {
// placeholder
font-size: 32px;
text-align: right;
color: $color-text-b3;
font-weight: 400;
padding-right: 8px;
}
}
.at-icon {
// 后缀图标
margin-right: 14px;
&:before {
color: $color-text-9;
}
}
.perch {
// 占位后缀图标
opacity: 0;
}
}
}
/* eslint-disable no-undef */
import { Component, createRef } from "react";
import { View, Text, Switch, Form, Button } from "@tarojs/components";
class FormCom extends Component {
el = createRef();
constructor() {
super();
}
isVerifyPass(element) {
let res = true;
if (element) {
element?.map(formItem => {
if (formItem) {
formItem?.childNodes.map(child => {
if (child?.props?.class === "formTip") {
res = false;
}
});
}
});
}
return res;
}
formSubmit = e => {
const { onSubmit } = this.props;
onSubmit && onSubmit(e, this.isVerifyPass(this.el.current?.childNodes));
};
render() {
return (
<Form ref={this.el} {...this.props} onSubmit={this.formSubmit}>
{this.props.children}
</Form>
);
}
}
export default FormCom;
//utils/rules.js
export function rulePhone(rule, value) {//手机号码
if (!value) return true
if (/^1[3-9]\d{9}$/.test(value)) return true
return false;
}
...
formSubmit = (e, isPass) => {
console.log("是否通过:", e, isPass);
};
//render
<FormCom
onSubmit={(e, isPass) => this.formSubmit(e, isPass)}
>
<FormItem
name="add"
title="手机号码"
prefix={<AtIcon size={10} value="add" />}
// suffix={<AtIcon size={20} value="chevron-right" />}
enter
rules={[
{ required: true, message: "请输入手机号" },
{
validator: (rule, value) => rulePhone(rule, value),
message: "请输入正确的手机号"
}
]}
>
<AtInput
value={this.state.form.phone}
onChange={val => {
this.setState({
form: { ...this.state.form, phone: val }
});
}}
placeholder="我是默认提示"
/>
</FormItem>
<AtButton
className="trace-btn-default"
type="primary"
circle
formType="submit"
>
提交
</AtButton>
</FormCom>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。