Class Component(ts)(v4)

Class Component

一种使用typescriptclass声明组件的方式。

IWidget类型声明

IWidget是平台内所有组件的统一接口定义,也是一个组件定义的最小集。

/**
 * 组件构造器
 */
export type WidgetConstructor<Props extends WidgetProps, Widget extends IWidget<Props>> = Constructor<Widget>;

/**
 * 组件属性
 */
export interface WidgetProps {
  [key: string]: unknown;
}

/**
 * 组件
 */
export interface IWidget<Props extends WidgetProps = WidgetProps> extends DisposableSupported {
  /**
   * 获取当前组件响应式对象
   * @return this
   */
  getOperator();

  /**
   * 组件初始化
   * @param props 属性
   */
  initialize(props: Props);

  /**
   * 创建子组件
   * @param constructor 子组件构造器
   * @param slotName 插槽名称
   * @param props 属性
   * @param specifiedIndex 插入/替换指定索引的子组件
   */
  createWidget<ChildProps extends WidgetProps = WidgetProps>(
    constructor: WidgetConstructor<ChildProps, IWidget<ChildProps>>,
    slotName?: string,
    props?: ChildProps,
    specifiedIndex?: number
  );
}

Widget

Widget是平台实现的类似于Class Component组件抽象基类,定义了包括渲染、生命周期、provider/inject、watch等相关功能。

export abstract class Widget<Props extends WidgetProps = WidgetProps, R = unknown> implements IWidget<Props> {
  /**
   *  添加事件监听
   *
   * @param  {string} path 监听的路径
   * @param  {deep?:boolean;immediate?:boolean} options?
   *
   * @example
   *
   * @Widget.Watch('formData.name', {deep: true, immediate: true})
   * private watchName(name: string) {
   *   ... todo
   * }
   *
   */
  protected static Watch(path: string, options?: { deep?: boolean; immediate?: boolean });

  /**
   * 可以用来处理不同widget之间的通讯,当被订阅的时候,会将默认值发送出去
   *
   * @param  {Symbol} name 唯一标示
   * @param  {unknown} value? 默认值
   *
   * @example
   *
   * const identifier = Symbol('example-sub')
   *
   * * field.ts * // 文件
   *
   * @Widget.BehaviorSubContext(identifier, {value: '这是默认值'})
   * private exampleSub!:WidgetBehaviorSubjection<{value: string}>
   *
   * onValueChange() {
   *   this.exampleSub.subject.next({value: '这是新的值'})
   * }
   *
   * * other-field.ts * // 文件
   * @Widget.BehaviorSubContext(identifier, {value: '这是默认值'})
   * private exampleSub!:WidgetBehaviorSubjection<{value: string}>
   *
   * mounted() {
   *  this.exampleSub.subscribe((value) => {
   *    ...todo
   *  })
   * }
   *
   */
  protected static BehaviorSubContext(name: Symbol, value?: unknown);

  /**
   * 与 `BehaviorSubContext` 一样,区别在于第一次不会发射默认值
   *
   * @param  {Symbol} name 唯一标示
   * @param  {unknown} value? 默认值
   */
  protected static SubContext(name: Symbol, value?: unknown);

  /**
   * 将数据绑定为响应式,并且组件中可以获取该值
   */
  protected static Reactive(params?: { displayName?: string; render?: boolean });

  /**
   * 将方法绑定为能够被组件获取的方法
   */
  protected static Method(displayName?: string);

  /**
   * 获取上级注入的依赖,与 Provide 一起使用
   *
   * @param  {string|Symbol} injectName? 被注入的name,如果不传递,那么取target中的name
   *
   * @example
   *
   * * children.ts * // 文件
   *
   * @Widget.Inject('InjectName')
   * private rootData!:
   *
   * 如果要将该值变为响应式,如果加上Reactive
   *
   *  @Widget.Reactive()
   *  @Widget.Inject('InjectName')
   *  private rootData!:;
   */
  protected static Inject(injectName?: string | Symbol);

  /**
   * 获取下级注入的依赖,与 Inject 一起使用
   *
   * @param  {string|Symbol} provideName? 被注入的name,如果不传递,那么取target中的name
   *
   * @example
   *
   * * parent.ts * // 文件
   *
   * @Widget.Provide('ProvideName')
   * private rootData!:
   *
   * 如果要将该值变为响应式,如果加上Reactive
   *
   *  @Widget.Reactive()
   *  @Widget.Provide('ProvideName')
   *  private rootData!:;
   */
  protected static Provide(provideName?: string | Symbol);

  /**
   * 通过唯一键获取对应组件
   * @param handle 唯一键
   */
  public static select(handle: string): Widget | undefined;

  public constructor(handle?: string);

  /**
   * 获取当前组件响应式对象
   */
  public getOperator();

  /**
   * 组件初始化
   * @param props 属性
   */
  public initialize(props: Props = {} as Props);

  /**
   * 获取组件唯一键
   */
  public getHandle(): string;

  /**
   * 创建一个widget
   *
   * @param constructor 对应的widget
   * @param name 插槽
   * @param config widget中initialize方法接收的参数
   * @param specifiedIndex 插入到对应位置的索引
   */
  public createWidget<T extends Widget>(
    constructor: WidgetConstructor<T['config'], T>,
    name?: string,
    config?: T['config'],
    specifiedIndex?: number
  );

  /**
   * 销毁当前widget
   */
  public dispose();

  /**
   * 获取父widget
   */
  public getParent(): Widget | undefined;

  /**
   * 获取所有的children
   */
  public getChildren(): Widget[];

  /**
   * 组件渲染
   * @param args 任意渲染参数
   * @return 框架VDom
   */
  public abstract render(...args): R;

  /**
   * beforeCreated 钩子函数
   * @protected
   */
  protected beforeCreated(): void;

  /**
   * created 钩子函数
   * @protected
   */
  protected created(): void;

  /**
   * beforeMount 钩子函数
   * @protected
   */
  protected beforeMount(): void;

  /**
   * mounted 钩子函数
   * @protected
   */
  protected mounted(): void;

  /**
   * beforeUpdate 钩子函数
   * @protected
   */
  protected beforeUpdate(): void;

  /**
   * updated 钩子函数
   * @protected
   */
  protected updated(): void;

  /**
   * activated 钩子函数
   * @protected
   */
  protected activated(): void;

  /**
   * deactivated 钩子函数
   * @protected
   */
  protected deactivated(): void;

  /**
   * beforeUnmount 钩子函数
   * @protected
   */
  protected beforeUnmount(): void;

  /**
   * unmounted 钩子函数
   * @protected
   */
  protected unmounted(): void;
}

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

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

Like (0)
oinone's avataroinone
Previous 2023年6月20日 pm4:07
Next 2023年11月2日 pm1:58

相关推荐

  • 提交数据动作如何把弹窗内的数据完全返回

    场景介绍 表格行的操作列有一个打开弹窗的动作 弹窗内为表格行数据的表单,表单内有一个o2m字段,展示了除关联关系字段(大部分场景为id)外的其他字段 弹窗底部动作区域有一个提交数据的客户端动作,该动作会将弹窗内表单的数据回写到表格行的数据上 场景截图 问题现象 点击提交数据的客户端动作,会将数据回写到表格行的数据上,但是表格行拿到的o2m字段的数据只有id字段,o2m字段的编码和名称并不会提交到表格行,o2m字段默认提交规则是只会提交关联关系字段(大部分场景为id)的数据 解决方案 该方案适合5.x版本,4.x版本新建的字段组件无法自动生成属性面板,建议拿下面的组件在SPI加上model和name注册实现 自定义o2m字段所在的组件,m2m字段或者其他类似问题的组件也是如下面组件一样覆写submit方法即可 import { BaseFieldWidget, FormO2MTableFieldWidget, ModelFieldType, SPI, SubmitRelationValue, SubmitValue, ViewType } from '@kunlun/dependencies'; @SPI.ClassFactory( BaseFieldWidget.Token({ viewType: ViewType.Form, ttype: ModelFieldType.OneToMany, widget: 'SubmitAllDataO2MTable' }) ) export class MyFormO2MTableFieldWidget extends FormO2MTableFieldWidget { public async submit(submitValue: SubmitValue): Promise<Record<string, unknown> | SubmitRelationValue | undefined> { return { [this.itemName]: this.value }; } } 在界面设计器的组件功能内新增对应业务类型的自定义组件,组件内的元件api名称填写上面组件的名称SubmitAllDataO2MTable 在界面设计器的设计页面切换o2m字段组件为SubmitAllDataO2MTable 参考文档 自定义组件文档

    2024年6月28日
    2.0K00
  • 组件生命周期(v4)

    阅读之前: 你应该: 了解DSL相关内容。母版-布局-DSL 渲染基础(v4) 对第三方框架的组件生命周期有所了解。如Vue组件生命周期 了解平台实现的Class Component(ts)相关内容。Class Component(ts)(v4) 组件生命周期 任何一个Widget其标准生命周期应当包括beforeCreated、created、beforeMount、mounted、beforeUnmount、unmounted这六个基本的生命周期函数、以及beforeUpdate和updated在响应式更新时会进行调用的生命周期函数。特别的,还有activated和deactivated在组件搭配keep-alive特性时使用的生命周期函数。 具体的生命周期执行过程在这里不再进行赘述,这里的基本逻辑与Vue组件生命周期基本完全一致,感兴趣的读者可以阅读Vue相关文档进行学习。

    2023年11月1日
    1.7K10
  • 页面出现中文乱码,该怎么解决?

    可能性1: 后端读取视图的xml解析时,由于系统缺少中文字体,导致解析后出现乱码,这种问题常见于采用docker镜像部署的情况,很多基础镜像不带中文字体。 解决方案:在物理系统或者docker镜像内安装中文字体 可能性2: win环境下未指定文件的编码类型 解决方案: 启动命令中加上-Dfile.encoding=UTF-8参数 # 示例命令 java -jar -Dfile.encoding=UTF-8 pamirs-demo-boot-1.0.0-SNAPSHOT.jar -Plifecycle=INSTALL

    2023年11月1日
    1.6K00
  • 主题设置-设置表格全局样式

    在启动工程的main.ts通过主题配置表格全局样式 registerThemeItem('demoTheme', { 'table-config': { // 是否带有边框 default(默认), full(完整边框), outer(外边框), inner(内边框), none(无边框) border: 'full', // 是否带有斑马纹 stripe: false, // 当鼠标点击行时,是否要高亮当前行 isCurrent: true } as Partial<TableThemeConfig> }); VueOioProvider( { browser: { title: 'Oinone – 构你想象!', favicon: 'https://pamirs.oss-cn-hangzhou.aliyuncs.com/pamirs/image/default_favicon.ico' }, theme: ['demoTheme'], // 其他代码 });

    2024年8月2日
    1.4K00
  • 【前端】登录页面扩展点

    登录页面扩展点 场景 1: 登录之前需要二次确认框2: 前端默认的错误提示允许被修改3: 后端返回的错误提示允许被修改4: 登录后跳转到自定义的页面 方案 前端默认错误可枚举 errorMessages: { loginEmpty: '用户名不能为空', passwordEmpty: '密码不能为空', picCodeEmpty: '图形验证码不能为空', phoneEmpty: '手机号不能为空', verificationCodeEmpty: '验证码不能为空', picCodeError: '图形验证码错误', inputVerificationCodeAlign: '请重新输入验证码' } 登录按钮添加拓展点beforeClick、afterClick 代码 新增一个ts文件,继承平台默认的LoginPageWidget @SPI.ClassFactory(RouterWidget.Token({ widget: 'Login' })) export class CustomLoginPageWidget extends LoginPageWidget { constructor() { super(); // 修改前端默认的错误文案 this.errorMessages.loginEmpty = '登录用户名不能为空'; } /** * 用来处理点击「登录」之前的事件,可以做二次确定或者其他的逻辑 * 只有return true,才会继续往下执行 */ public beforeClick(): Promise<Boolean | null | undefined> { return new Promise((resolve) => { Modal.confirm({ title: '提示', content: '是否登录?', onOk: () => { resolve(true); } }); }); } /** * * @param result 后端接口返回的数据 * * 用来处理「登录」接口调用后的逻辑,可以修改后端返回的错误文案,也可以自定义 * * 只有return true,才会执行默认的跳转事件 */ public afterClick(result): Promise<any | null | undefined> { // if(result.redirect) { // 自定义跳转 //return false //} if (result.errorCode === 20060023) { result.errorMsg = '手机号不对,请联系管理员'; } return result; } }

    2023年11月1日
    1.3K00

Leave a Reply

Please Login to Comment