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

相关推荐

  • 根据固定的接口返回数据动态控制按钮的显隐

    在项目开发中,我们经常会面临这样的情况:当前按钮的显示与隐藏需要根据后端某个接口返回的数据来决定,而无法通过权限配置进行处理。为了解决这个问题,我们可以通过自定义的方式来处理这一功能。 首先,我们需要知道当前动作是什么类型的动作,例如「服务端动作、跳转动作、打开弹窗的动作、打开抽屉的动作」。 ServerActionWidget -> 服务端动作DialogViewActionWidget -> 打开弹窗动作DrawerViewActionWidget -> 打开抽屉动作RouterViewActionWidget -> 路由跳转动作 下面是一个示例代码,演示了如何通过自定义的方式处理按钮的显示与隐藏逻辑。 import { ActionType, ActionWidget, SPI, ServerActionWidget, Widget, http } from '@kunlun/dependencies'; @SPI.ClassFactory( ActionWidget.Token({ actionType: ActionType.Server, model: 'resource.k2.Model0000000100', name: 'create' }) ) export class MyAction extends ServerActionWidget { // 当前动作是服务端动作,继承的是 ServerActionWidget @Widget.Reactive() private needInvisible = false; @Widget.Reactive() public get invisible(): boolean { return this.needInvisible; } protected mounted(): void { super.mounted(); // 模拟接口 http.query(模块名, `graphql`).then(res => { if(res) { this.needInvisible = true } }) } } 在实际应用中,我们可以调用后端接口,根据返回的数据动态修改 needInvisible 这个值,从而实现按钮的动态显示与隐藏效果。这样的设计使得按钮的显示状态更加灵活,并且能够根据后端数据动态调整,提高了系统的可定制性。

    前端 2023年11月23日
    2.0K00
  • 【动作】-路由动作跳转后如何主动刷新页面数据

    介绍 当我们使用多tab组件的时候,如果一个viewAction已经打开了一个tab页,再次用该viewAction打开页面的时候,会发现不会根据路由上的业务参数(如详情和编辑页的id参数)主动刷新数据,这个时候可以通过以下方法解决该问题 // 该方法可以在进入新路由页面后刷新数据,推荐将该方法放到工具类 function refreshViewAction(action: any) { const onRefreshTabWithActive = (manager: MultiTabsManager, instance: MultiTabInstance) => { // 进入路由后刷新页面数据 manager.refresh(instance.key); manager.clearOnActive(onRefreshTabWithActive); }; MultiTabsManager.INSTANCE.onActive(onRefreshTabWithActive); executeViewAction(action); } 将原本调用executeViewAction的方法改为refreshViewAction 如果需要扩展executeViewAction的其他入参请自行拓展refreshViewAction的入参

    2024年6月18日
    1.9K00
  • 左树右表默认选择第一行

    import { BaseElementWidget, Widget, SPI, ViewType, TableSearchTreeWidget } from '@kunlun/dependencies'; @SPI.ClassFactory( BaseElementWidget.Token({ viewType: ViewType.Table, widget: 'tree', model: '改成当前视图的模型' }) ) export class CustomTableSearchTreeWidget extends TableSearchTreeWidget { protected hasExe = false; @Widget.Watch('rootNode.children.length') protected watchRootNode(len) { if (len && !this.hasExe) { this.hasExe = true; const firstChild = this.rootNode?.children?.[0]; if (firstChild) { this.onNodeSelected(firstChild); this.selectedKeys = [firstChild.key]; } } } }

    2024年11月26日
    1.4K00
  • 列表页内上下文无关的动作如何添加自定义上下文

    场景 在界面设计器,可以配置当前列表页从上个页面带的上下文参数,现在需要传递这个上下文到下个页面,设计器没有配置入口,我们可以通过自定义改动作来解决 示例代码 import { ActionType, ActionWidget, RouterViewActionWidget, SPI, ViewActionTarget } from '@kunlun/dependencies'; @SPI.ClassFactory( ActionWidget.Token({ actionType: [ActionType.View], target: [ViewActionTarget.Router], // 模型编码 model: 'module.model', // 动作名称 name: 'actionName' }) ) export class DemoRouterViewActionWidget extends RouterViewActionWidget { protected async clickAction(): Promise<void> { // initialContext内是上个页面传来的上下文,手动将值传递到下个页面的上下文 // 这里假设需要传递的字段名为type this.action.context = { type: this.initialContext.type }; return super.clickAction(); } }

    2024年8月20日
    2.3K00
  • 打开弹窗的action,传入默认的查询条件不生效

    场景 form视图中的action,点击后打开table的弹窗的,xml中配置的filter,但是table查询的时候没有带上查询条件: <action name=”action_name” label=”打开tabel弹窗视图” filter=”id==${activeRecord.id}” /> 解决方案 将xml中的activeRecord修改成openerRecord即可。 <action name=”action_name” label=”打开tabel弹窗视图” filter=”id==${openerRecord.id}” />

    2023年11月1日
    2.2K00

Leave a Reply

Please Login to Comment