Skip to content

Latest commit

 

History

History
136 lines (112 loc) · 5.11 KB

README.md

File metadata and controls

136 lines (112 loc) · 5.11 KB

from 表单组件

这里只实现两个核心组件<TheForm /><TheFormItem />;因为移动端样式变化比较灵活,如果把所有表单组件都封装成element-ui或者vant-ui这类型一体库的话,导致很多无用代码和性能开销,所以这里只提供必需的功能组件,其他表单组件根据实际情况定义,保证高度灵活性。

<TheForm />

参数说明:

props 类型 是否必选 说明
model object 表单绑定的值(表单数据)
rules object 表单验证数据(和element-ui一致)
labelWidth string 表单字段宽度,pxrpx%
labelPosition string: left,right,top 表单字段排版,默认left
border boolean 是否需要显示底部边框,默认false
validateScroll boolean 是否需要在验证时,滚动到不通过的位置,默认true,短表单时建议关闭,长表单开启

element-ui差异:

  • props.rules移除了validator,增加了reg正则匹配:注意:因为微信小程序的一些特殊机制,导致传参类型会把非 number|string|object 的类型过滤掉,所以这里在写正则的时候,在末尾加上.toString()即可;
  • props.rules移除了change触发条件,组件内部做了智能触发机制;

事件/方法说明:

方法 参数 参数说明 说明
validate(callback(...)) callback(isValid, rules) 有两个回调参数,和element-ui一致 表单验证
validateField(prop, callback(...)) prop是指定验证的键值,callback和上面一致 有两个回调参数,和element-ui一致 指定验证某个字段
resetFields() - - 移除所有校验
resetField(prop) prop是指定移除验证的键值 - 移除指定校验

<TheFormItem />

参数说明:

props 类型 是否必选 说明
prop string 表单对象key字段
rules array 这里是上面rules对象里面的数组,类型一致;优先级高于父组件
label string 表单展示字段
labelWidth string 表单字段宽度,pxrpx%;优先级高于父组件
labelPosition string: left,right,top 表单字段排版,默认left;优先级高于父组件
border boolean 是否需要显示底部边框,默认false;优先级高于父组件

使用示例

<template>
  <view>
    <TheForm :model="formData" :rules="formRules" labelWidth="160rpx" labelPosition="left" ref="theForm">
      <TheFormItem prop="userName" label="用户名">
        <input class="the-input" type="text" v-model="formData.userName" :placeholder="formRules.userName[0].message">
      </TheFormItem>
      <TheFormItem prop="phone" label="用户手机号">
        <input class="the-input" type="number" v-model="formData.phone" :placeholder="formRules.phone[0].message">
      </TheFormItem>
      <TheFormItem prop="avatar" label="用户头像" :border="false">
        <UploadImage :src="formData.avatar" @change="onUpload" />
      </TheFormItem>
    </TheForm>
    <button @click="onSubmit()">提交表单</button>
    <button @click="onReset()">重置表单</button>
    <button @click="validatePhone()">验证手机号码</button>
    <button @click="resetPhone()">重置验证手机号码</button>
  </view>
</template>

<script setup lang="ts">
import { reactive, ref } from "vue";
import TheForm from "@/components/Form/TheForm.vue";
import TheFormItem from "@/components/Form/TheFormItem.vue";
import UploadImage from "@/components/Upload/Image.vue";
// import { TheForm, TheFormItem } from "@/components/Form";
// import { UploadImage } from "@/components/Upload";
import { showToast } from "@/utils/control";
import type { TheFormRules, UploadChange } from "@/types";

const hasBorder = ref(true);

const formData = reactive({
  userName: "",
  phone: "",
  avatar: ""
})

const formRules: TheFormRules = {
  userName: [
    { required: true, message: "请输入用户名" }
  ],
  phone: [
    { required: true, message: "请输入用户手机号" },
    { reg: /^1[345678]\d{9}$/.toString(), message: "手机号不正确" }
  ]
}

const theForm = ref<InstanceType<typeof TheForm>>();

function onUpload(res: UploadChange) {
  formData.avatar = res.src;
}

function onSubmit() {
  theForm.value!.validate((valid, rules) => {
    if (valid) {
      console.log("表单数据 >>", formData);
    } else {
      const keys = Object.keys(rules);
      const firstProp = keys[0];
      showToast(`${rules[firstProp][0].message}`);
    }
  })
}

function onReset() {
  theForm.value!.resetFields();
}

/** 验证手机号码 */
function validatePhone() {
  theForm.value!.validateField("phone", (valid, rules) => {
    if (valid) {
      showToast("手机验证通过");
    } else {
      showToast(rules["phone"][0].message!);
    }
  })
}

/** 移除验证手机号 */
function resetPhone() {
  theForm.value!.resetField("phone");
}
</script>