表单组件的控制类属性细节 - 你的表单设计器还有哪些没考虑到的地方?

在开发表单库的过程中,我们免不了需要控制每个组件的显隐,是否禁用等属性,对于所有的属性,我总结在了这篇文章:《封装表单元素,应该定义哪些状态或属性》。其中有这么一类属性:hiddenoptionaldisabled,这类属性负责控制那个组件的使用规则,我统一归纳为控制类属性,这篇文章我详细讲讲这些属性的意义。

"属性"还是"状态"

我们先确定"属性"和"状态"的含义。"属性"和"状态"的区别在于以下几点:

  • "属性"是来自外部的控制,组件自身无法改变;"状态"是来自内部的变化,外部不应该能够修改;
  • "属性"是用来控制那个组件的工作方式;"状态"是用来保存交互时的动态数据;
  • "属性"是相对确定的,父组件的属性不变,子组件的属性也不会变;"状态"会通过组件自身的逻辑随时变换。

现在来看visible(是否显示)和touched(用户是否点击过),这两个就好区分了,visible属于属性,touched属于状态。

"属性"和"状态"并不是绝对的 ,这里visible相对于touched更像是"属性",而某种程度visible也是动态的,下面会细讲。

Form Array

我们举一个简单的例子,假设有两个input:fName用来输入名字,lName用来输入姓氏,那么对这个form,我们可以用以下JSON Schema来定义:

json 复制代码
{    // <--- 用key-value表示,而不是array
    fName: {
        name: "fName",
        label: "First Name",
        type: "text",
        ...
    },
    lName: {
        name: "fName",
        label: "First Name",
        type: "text",
        ...
    }
}

随着用户的输入,我们的框架可以自动获取整个form值,比如:{ fName: "Jenny", lName: "Han" }

这里可能会有人有疑问为什么定义form不是用的array,而是用key-value对,一个是因为form值本身就是key-value的,所以这里用key-value来定义让格式更一致;更重要的原因是要考虑到有一种并列数据输入的情况,比如说这个表单是个可以添加多个不同人名的表单 ,于是会有很多个fNamelName,每对fNamelName是并列的,用户可以输入一对,也可以输入多对,这种情况,我们再用array来表示。

available

回到正题,控制类属性中,假如此时我将fNamehidden设为true,就意味着fName这个input看不见了,但实际上这个form值还是{ fName: "Jenny", lName: "Han" },因为hidden只控制着组件的显示或隐藏,并不会让值有变化。可以实际使用场景,当一个组件隐藏了,有时候我们需要保留它之前的值,而有时候是需要将那个字段踢出去的,这里是很多低代码表单设计器没有考虑到的地方。

因此,我引入了available这个属性,当availabletrue时,字段是可以包括在内的,为false时,字段是会被踢出去的。 这样当fNameavailablefalse时,这个form的值会自动变为{ lName: "Han" },这样让前端的值变得更准确和自动化。

注意:这里不用用validinvalid这类词汇,因为这些在校验类状态中会用到。

语义方向一致

对于显隐,有时候用hidden,有时候用visible;对于必填还是选填,有时候用mandatoryrequired,有时候用optional;对于可用还是禁用,有时候用disabled,有时候用enabled。这些语义不统一的话,使用起来总要考虑是不是要取非,很容易混淆。尤其是在还有嵌套表单时,父表单disabled,子表单里的某个组件enabled,这类计算稍不注意就会出错。

因此这里我将语义全部统一为正向的,即:visiblerequiredenabledavailable

动态化

由于表单联动是很常见的,比如这里当我fName"Jenny"时,lName才显示,否则不显示,这种情况我们需要向用户开放一个属性visibleOn,让用户来定义什么时候是visible的,其他时候则为非visible的。对应的还有requiredOn, enabledOn, availableOn

要注意的是这些属性是开放给用户的,而在表单中,我们还需要一些逻辑来计算出boolean值。也就是动态地,通过visibleOn计算当前visible值,通过requiredOn计算当前required值,通过enabledOn计算当前enabled值,通过availableOn计算当前available值,再将这些boolean属性传给对应的子组件。

上面说过"属性"和"状态"并不是绝对的,这里便可以看出,visiblevisibleOn一起看,visible更像是状态,而visibleOn更像是属性。

封装

我们在封装单个组件时,react中可以写成这样:

js 复制代码
const FreeField = ({ visibleOn, requiredOn, enabledOn, availableOn }) => {
    
    return (
        <ControllingField
            visibleOn={visibleOn}
            requiredOn={requiredOn}
            enabledOn={enabledOn}
            availableOn={availableOn}
        >
            {({ visible, required, enabled, available }) => {
                return (
                    <Text 
                        visible={visible}
                        required={required}
                        enabled={enabled}
                        available={available}
                        ...
                    />
                );
            }}
        </ControllingField>
    );
}

接下来我们的工作重心就在于ControllingField中将xxxOn属性计算成boolean属性了。

相关推荐
PleaSure乐事几秒前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶1 分钟前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json
getaxiosluo2 分钟前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v5 分钟前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript
易云码29 分钟前
信息安全建设方案,网络安全等保测评方案,等保技术解决方案,等保总体实施方案(Word原件)
数据库·物联网·安全·web安全·低代码
栈老师不回家1 小时前
Vue 计算属性和监听器
前端·javascript·vue.js
前端啊龙1 小时前
用vue3封装丶高仿element-plus里面的日期联级选择器,日期选择器
前端·javascript·vue.js
一颗松鼠1 小时前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
小远yyds2 小时前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
阿伟来咯~2 小时前
记录学习react的一些内容
javascript·学习·react.js