Skip to content
本页内容

扩展函数

项目表单设计中,可能需要在触发表单 form 或流程 flow 事件时,执行自己提供的函数取代平台行为,那么可以通过注册并执行扩展函数 Extension Function 的方式来实现这个需求。

注册

index.html 入口使用 script 引入,将其内部的函数、变量等添加到全局 window 环境中。

注册

由于函数注入后将始终存在于全局环境中,函数编写时请避免名称冲突,并且注入后在整个项目生命周期中都可调用,无需重复注册。

触发

完成注册后,要触发扩展函数,你只需在对应控件或流程的事件中编写 function() 即可,function 为函数名称,平台会优先判断该名称是否为平台内置函数,如果不是则将该函数视为需要执行的扩展函数。

例, 设置自定义流程发送事件:

ts
// 构建流程节点中设置流程事件
myFlowSend()
// 构建流程节点中设置流程事件
myFlowSend()

那么,在运行平台点击该节点时,平台会先判断出 myFlowSend 并不是内置函数,则将该指令视为扩展函数并执行:

ts
const extendFunction = window.MYFLOWSEND

if (typeof extendFunction === 'function') {
  // 执行 window 下的扩展事件
  await window.MYFLOWSEND(render, event)
}
const extendFunction = window.MYFLOWSEND

if (typeof extendFunction === 'function') {
  // 执行 window 下的扩展事件
  await window.MYFLOWSEND(render, event)
}

可以看到,此时运行平台将尝试从 window 中获取 MYFLOWSEND 函数并且以同步 async await 的方式去执行它。

大小写

在示例中我们发现,构建注册的扩展函数在运行平台执行时已转为全大写。这是因为多个构建人员编写函数时容易忽视函数名大小写问题,所以在实际执行时统一转化以避免拼写错误。

因此,注册扩展函数时函数名也请统一采用全大写风格。

ts
// myFunc.js

function MYFLOWSEND(render) {
  // do your flow send code
}
// myFunc.js

function MYFLOWSEND(render) {
  // do your flow send code
}

同步

有时你会需要扩展函数能以同步的方式执行,如平台在流程保存前提供了生命周期钩子 beforeFormSave,此时你注册的扩展函数会发送一个异步请求获取数据再判断能否保存,那么平台在扩展函数中的异步请求返回结果前都要等待(同步)。

由于平台执行扩展函数时,都会添加 await 标识,你只需要以 asyncpromise 同步。

  • Async:

    ts
    const beforeFormSave = async (render) => {
      // ...
      await getAxiosData()
    }
    
    const beforeFormSave = async (render) => {
      // ...
      await getAxiosData()
    }
    
  • Promise:

    ts
    const beforeFormSave = async (render) => {
      return new Promise((resolve, reject) => {
        getAxiosData().then((res) => resolve())
      })
    }
    
    const beforeFormSave = async (render) => {
      return new Promise((resolve, reject) => {
        getAxiosData().then((res) => resolve())
      })
    }
    

表单事件

平台的每一步操作都会创建一个表单事件对象,它包含了将要执行动作的所需信息,类型为:

ts
interface CoEvent extends OptionProps {
  /**
   * 事件类型,属于流程事件或表单事件
   */
  type: 'flow' | 'form'
  /**
   * 表单编号
   */
  form?: string
  /**
   * 流程编号
   */
  flow: string
}
interface CoEvent extends OptionProps {
  /**
   * 事件类型,属于流程事件或表单事件
   */
  type: 'flow' | 'form'
  /**
   * 表单编号
   */
  form?: string
  /**
   * 流程编号
   */
  flow: string
}

其余部分参数与 render.setForm 一致。

示例

core^6.2 版本中,运行平台路径 extensions/functions/demo.js 有如下示例扩展:

js
async function DEMO(render, event) {
  return new Promise((resovle) => {
    if (!render.getCtrlValue('primary-ctrl'))
      return reject(
        render.createError({
          type: 'warning',
          message: '主键不存在',
          log: '[save warn]:primary id is not existed.',
        })
      )

    resovle()
  })
}
async function DEMO(render, event) {
  return new Promise((resovle) => {
    if (!render.getCtrlValue('primary-ctrl'))
      return reject(
        render.createError({
          type: 'warning',
          message: '主键不存在',
          log: '[save warn]:primary id is not existed.',
        })
      )

    resovle()
  })
}

扩展函数将接收平台传来的两个参数:

  • render 运行平台当前表单实例
  • event 当前执行表单事件对象

平台在该扩展返回结果 (resolve, reject) 前不会继续执行后续事件,或者在接收到 异常 时中断。

Powerd by Vitepress.