字段组件submit方法详解

场景介绍

在日常开发调试表单页的过程中,细心的小伙伴应该注意到,视图内的数据(通过vue调试工具看到的formData就是视图的数据)和最终通过服务端动作提交的数据不总是一致的,本文将带领大家解开疑惑。

为什么会出现这种现象?

出现这种情况都是当前模型上有关联关系字段的场景,以多对一(M2O)场景为例,由于当前模型的关联关系字段是通过字段配置中的referenceFields属性和当前模型的relationFields属性进行关联的,所以提交数据的时候只需要拿到relationFields配置的字段就可以了,没有必要再去多拿关联关系字段本身的数据。

结合业务场景说明

这里以商品模型和类目模型举例,商品模型内有个类目的m2o字段category和对应的relationFields字段categoryId,数据提交到后端的时候前端默认会根据字段配置只获取categoryId,而category的整个对象都不会被提交。

package pro.shushi.pamirs.demo.api.model;

import pro.shushi.pamirs.demo.api.model.DemoItemCategory;
import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.base.common.CodeModel;

@Model.model(DemoItem.MODEL_MODEL)
@Model(displayName = "测试商品")
public class DemoItem extends CodeModel {

    private static final long serialVersionUID = -5104390780952631397L;

    public static final String MODEL_MODEL = "demo.DemoItem";

    @Field.String
    @Field(displayName = "商品名称")
    private String name;

    @Field.Integer
    @Field(displayName = "类目ID")
    private Long categoryId;

    @Field.many2one
    @Field.Relation(relationFields = {"categoryId"}, referenceFields = {"id"})
    @Field(displayName = "商品类目")
    private DemoItemCategory category;
}

前端是如何处理数据的

前端的字段组件提供了submit()方法来让我们可以有就会在提交数据的时候改变数据。

// 字段组件基类
export class BaseFormItemWidget<
  Value = unknown,
  Props extends BaseFormItemWidgetProps = BaseFormItemWidgetProps
> extends BaseDataWidget<Props> {
 /**
   * 数据提交的方法,例如:m2o字段user(假设其关系字段为userId)的值{id: 1, name: 'xxx'},但是实际后端数据只需要其中的id,所以用m2o对应的关系字段userId提交数据就可以了
   * @param submitValue
   */
  public submit(submitValue: SubmitValue): ReturnPromise<Record<string, unknown> | SubmitRelationValue | undefined> {
    return undefined;
  }
}

这里先以FormStringFieldSingleWidget组件处理密码类型的字段讲解。
密码一般在输入的时候是明文,为了提高提交到后端的安全性,可以将这个密码加密后再传到后端,后端再做进一步处理,这个场景中,视图中的密码和提交给后端的密码就出现了不一致的情况,

@SPI.ClassFactory(
  BaseFieldWidget.Token({
    viewType: [ViewType.Form, ViewType.Search],
    ttype: ModelFieldType.String
  })
)
export class FormStringFieldSingleWidget extends FormStringFieldWidget {
  public submit(submitValue: SubmitValue) {
    let finalValue = this.value;
    /**
     * 数据提交的时候,如果判断当前字段是否需要加密,需要加密的情况用encrypt函数做加密处理
     */
    if (this.crypto && finalValue) {
      finalValue = encrypt(finalValue);
    }
    return SubmitHandler.DEFAULT(this.field, this.itemName, submitValue, finalValue);
  }

注意:关系字段配置的透出字段只影响该字段的查询数据方法的返回值,不会因为此配置就在提交数据里加上这部分配置的字段

字段需要提交关联关系字段内的所有数据如何处理?

我们可以在自定义组件里覆写submit()方法,直接将this.value内的数据返回
这里以覆写多对多m2m字段为例

import {
  BaseFieldWidget,
  FormM2MFieldSelectWidget,
  ModelFieldType,
  SPI,
  SubmitValue,
  ViewType
} from '@kunlun/dependencies';

@SPI.ClassFactory(
  BaseFieldWidget.Token({
    viewType: ViewType.Form,
    ttype: ModelFieldType.ManyToMany,
    widget: 'Select',
    model: 'xxx.yyyyy',
    name: 'fileName01',
  })
)
export class MyFormO2MSubmitAllSelectFieldWidget extends FormM2MFieldSelectWidget {

  /**
   * 提交数据的方法
   * 重写后会将字段内所有数据都提交,默认的方法只会提交关联关系字段的数据
   * @param submitValue
   */
  public async submit(submitValue: SubmitValue) {
    // this.itemName是当前字段名称
    return { [this.itemName]: this.value };
  }
}

Oinone社区 作者:nation原创文章,如若转载,请注明出处:https://doc.oinone.top/frontend/17155.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

Like (0)
nation's avatarnation数式员工
Previous 2024年9月10日 am9:35
Next 2024年9月11日 am9:57

相关推荐

  • 后端代码规范

    前言 虽然oinone框架减少了很多的代码,但是低代码部分的代码质量也需要高度关注,不管是写的代码bug多,或者说被吐槽代码不行,还是说写的代码经常被重构,核心点还是没有代码规范的意识和技巧,下面摘录了一些常见的规范要求,去提高后端的代码质量,代码质量提高后,自然效率也会提升。 常见代码规范 **1、规范命名** 命名是写代码中最频繁的操作,比如类、属性、方法、参数等。好的名字应当能遵循以下几点: **见名知意** 比如需要定义一个变量需要来计数 int i = 0; 名称 i 没有任何的实际意义,没有体现出数量的意思,所以我们应当指明数量的名称 int count = 0; **能够读的出来** 如下代码: private String sfzh; private String dhhm; 这些变量的名称,根本读不出来,更别说实际意义了。 所以我们可以使用正确的可以读出来的英文来命名 private String idCardNo; private String phone; **2、规范代码格式** 好的代码格式能够让人感觉看起来代码更加舒适。 好的代码格式应当遵守以下几点: 合适的空格 代码对齐,比如大括号要对齐 及时换行,一行不要写太多代码 好在现在开发工具支持一键格式化,可以帮助美化代码格式,大家统一使用idea的规范即可。 **3、写好代码注释** 在《代码整洁之道》这本书中作者提到了一个观点,注释的恰当用法是用来弥补我们在用代码表达意图时的失败。换句话说,当无法通过读代码来了解代码所表达的意思的时候,就需要用注释来说明。 书的作者之所以这么说,是因为作者觉得随着时间的推移,代码可能会变动,如果不及时更新注释,那么注释就容易产生误导,偏离代码的实际意义。而不及时更新注释的原因是,程序员不喜欢写注释。😒 但是这不意味着可以不写注释,当通过代码如果无法表达意思的时候,就需要注释,比如如下代码: for (Integer id : ids) { if (id == 0) { continue; } //做其他事 } 为什么 id == 0 需要跳过,代码是无法看出来了,就需要注释了。 好的注释应当满足一下几点: 解释代码的意图,说明为什么这么写,用来做什么 对参数和返回值注释,入参代表什么,出参代表什么 有警示作用,比如说入参不能为空,或者代码是不是有坑 当代码还未完成时可以使用 todo 注释来标记 代码review发现漏洞时 可以使用 fixme 注释来标记 **4、try catch 内部代码抽成一个方法** try catch代码有时会干扰我们阅读核心的代码逻辑,这时就可以把try catch内部主逻辑抽离成一个单独的方法 如下图是Eureka服务端源码中服务下线的实现中的一段代码 整个方法非常长,try中代码是真正的服务下线的代码实现,finally可以保证读锁最终一定可以释放。 所以这段代码其实就可以对核心的逻辑进行抽取。 protected boolean internalCancel(String appName, String id, boolean isReplication) { try { read.lock(); doInternalCancel(appName, id, isReplication); } finally { read.unlock(); } // 剩余代码 } private boolean doInternalCancel(String appName, String id, boolean isReplication) { //真正处理下线的逻辑 } **5、方法别太长** 方法别太长就是字面的意思。一旦代码太长,给人的第一眼感觉就很复杂,让人不想读下去; 同时方法太长的代码可能读起来容易让人摸不着头脑,不知道哪一些代码是同一个业务的功能。 比如代码中有那种2000+行大类,各种if else判断,光理清代码思路就需要用很久时间。🤷🏻‍♀️ 所以一旦方法过长,可以尝试将相同业务功能的代码单独抽取一个方法,最后在主方法中调用即可。 **6、抽取重复代码** 当一份代码重复出现在程序的多处地方,就会造成程序又臭又长,当这份代码的结构要修改时,每一处出现这份代码的地方都得修改,导致程序的扩展性很差。 所以一般遇到这种情况,可以抽取成一个工具类,还可以抽成一个公共的父类。 **7、多用return** 在有时我们平时写代码的情况可能会出现if条件套if的情况,当if条件过多的时候可能会出现如下情况: if (条件1) { if (条件2) { if (条件3) { if (条件4) { if (条件5) { System.out.println("11111"); } } } } } 面对这种情况,可以换种思路,使用return来优化 if (!条件1) { return; } if (!条件2) { return; } if (!条件3) { return; } if (!条件4) { return; } if (!条件5) { return; } System.out.println("11111"); 这样优化就感觉看起来更加直观 **8、if条件表达式不要太复杂**…

    2024年12月11日
    3.3K00
  • 前端元数据介绍

    模型 属性名 类型 描述 id string 模型id model string 模型编码 name string 技术名称 modelFields RuntimeModelField[] 模型字段 modelActions RuntimeAction[] 模型动作 type ModelType 模型类型 module string 模块编码 moduleName string 模块名称 moduleDefinition RuntimeModule 模块定义 pks string[] 主键 uniques string[][] 唯一键 indexes string[][] 索引 sorting string 排序 label string 显示标题 labelFields string[] 标题字段 模型字段 属性名 类型 描述 model string 模型编码 modelName string 模型名称 data string 属性名称 name string API名称 ttype ModelFieldType 字段业务类型 multi boolean (可选) 是否多值 store boolean 是否存储 displayName string (可选) 字段显示名称 label string (可选) 字段页面显示名称(优先于displayName) required boolean | string (可选) 必填规则 readonly boolean | string (可选) 只读规则 invisible boolean | string (可选) 隐藏规则 disabled boolean | string (可选) 禁用规则 字段业务类型 字段类型 值 描述 String ‘STRING’ 文本 Text ‘TEXT’ 多行文本 HTML ‘HTML’ 富文本 Phone ‘PHONE’ 手机 Email ‘EMAIL’ 邮箱 Integer ‘INTEGER’ 整数 Long ‘LONG’ 长整型 Float ‘FLOAT’ 浮点数 Currency ‘MONEY’ 金额 DateTime ‘DATETIME’ 时间日期 Date ‘DATE’ 日期 Time ‘TIME’ 时间 Year ‘YEAR’ 年份 Boolean ‘BOOLEAN’ 布尔型 Enum ‘ENUM’ 数据字典 Map ‘MAP’ 键值对 Related ‘RELATED’ 引用类型 OneToOne ‘O2O’ 一对一 OneToMany ‘O2M’ 一对多 ManyToOne ‘M2O’ 多对一 ManyToMany ‘M2M’ 多对多 模型动作 属性名 类型 描述 name string…

    2024年9月21日
    2.3K00
  • 登录页自定义配置如何使用

    介绍 为满足大家对登录页面不同的展示需求,oinone在登录页面提供了丰富的配置项以支持大家在业务上的个性化需求 配置方式 在manifest.js内新增以下配置选项 manifest.js文件如何配置的参考文档 runtimeConfigResolve({ login: { /** * 登录按钮label */ loginLabel: '登录', /** * 是否显示忘记密码按钮 */ forgetPassword: true, /** * 忘记密码按钮Label */ forgetPasswordLabel: '忘记密码', /** * 是否显示注册按钮 */ register: true, /** * 注册按钮Label */ registerLabel: '注册', /** * 是否显示验证码登录Tab */ codeLogin: true, /** * 账号登录Tab Label */ accountLoginLabel: '账号', /** * 验证码登录Tab Label */ codeLoginLabel: '验证码', /** * 账号登录-账号输入框Placeholder */ accountPlaceholder: '请输入账号', /** * 账号登录-密码输入框Placeholder */ passwordPlaceholder: '前输入密码', /** * 验证码登录-手机号输入框Placeholder */ phonePlaceholder: '请输入手机号', /** * 验证码登录-验证码输入框Placeholder */ codePlaceholder: '请输入验证码', } });

    2024年4月24日
    2.6K00
  • 「前端」 获取当前用户信息以及语言

    概述 TopBarService 是用于管理用户信息和多语言配置的工具类,提供以下核心功能: 用户信息查询(含缓存机制) 当前语言状态获取 可用语言列表查询 语言切换操作 快速开始 // 基础使用示例 import { TopBarService } from '@kunlun/dependencies'; // 获取用户信息(自动缓存) const userInfo = await TopBarService.getUserInfo(); // 获取当前语言配置 const currentLang = await TopBarService.getCurrentLang(); // 查询支持的语言列表 const languages = await TopBarService.queryLanguageList(); // 激活指定语言 await TopBarService.activeLang('zh_CN'); API 详解 方法功能说明 方法名称 描述 参数 返回值 ​getUserInfo 获取当前用户信息(自动缓存) 无 用户信息对象 ​queryUserInfo 强制获取最新用户信息 无 最新用户信息对象 ​getCurrentLang 获取当前激活的语言配置 无 语言配置对象 / undefined ​queryLanguageList 获取所有可用语言列表 无 语言列表数组 ​activeLang 激活指定语言 语言 ID (string) 更新后的语言配置对象

    2025年3月21日
    2.1K00
  • 移动端5.0.x启动、打包代码报错

    在5.0.x版本中,移动端mobile-base包是源码开放的,所以项目在启动的时候可能会报错,请按照下面的步骤修改。 打开boot工程中的package.json "dependencies"中添加 "lodash-es": "4.17.21" "devDependencies"中添加 "@types/lodash-es": "4.17.12" 在main.ts中删除 import '@kunlun/vue-mobile-base/dist/kunlun-vue-mobile-base.css'

    2024年7月17日
    2.3K00

Leave a Reply

Please Login to Comment