Skip to content
导航栏

事件动作中的 reload action

在事件中使用 action 进行组件联动时,使用 reload 的同时进行 setValue 操作:

以下是个按钮的 click 事件,它会刷新加载另外一个 service 组件的内容。

使用 componentId 指定目标组件。

json
{
  "onEvent": {
    "click": {
      "actions": [
        {
          "type": "action",
          "actionType": "reload",
          "componentId": "u:70aaf268ffc5",
          "args": {
            "current_item": "${item}"
          }
        }
      ],
      "weight": 0
    }
  }
}

配置方法二: 先给 service 组件配置一个名称

json
{
  "onEvent": {
    "click": {
      "actions": [
        {
          "type": "action",
          "actionType": "reload",
          "componentName": "service1",
          "args": {
            "current_item": "${item}"
          }
        }
      ],
      "weight": 0
    }
  }
}

在 action 中如果需要查找目标组件,属性需要设置 componentId 或是 componentName,不能使用 target,CmptAction 并不支持这种配置格式。

执行的代码如以所示,原理是找到目标控件,执行目标控件的 reload 方法。

js
/*!node_modules/amis-core/lib/actions/CmptAction.js*/

/**
 * 根据唯一ID查找指定组件
 * 触发组件未指定id或未指定响应组件componentId,则使用触发组件响应
 */
const key = action.componentId || action.componentName;
const dataMergeMode = action.dataMergeMode || 'merge';

let component = key
  ? event.context.scoped?.[
      action.componentId ? 'getComponentById' : 'getComponentByName'
    ](key)
  : null;

// 刷新
if (action.actionType === 'reload') {
  return component?.reload?.(
    undefined,
    action.data, //{current_item: "admin_user"}
    undefined,
    undefined,
    dataMergeMode === 'override',
    action.args,
  );
}
js
// amis\packages\amis\src\renderers\Service.tsx

  reload(
    subpath?: string,
    query?: any,//查询参数
    ctx?: any,
    silent?: boolean,
    replace?: boolean
  ) {
    const scoped = this.context as IScopedContext;
    if (subpath) {
      return scoped.reload(
        query ? `${subpath}?${qsstringify(query)}` : subpath,
        ctx
      );
    }

    return super.reload(subpath, query, ctx, silent, replace);
  }

另外需要注意的是传值的方法,这里的携带参数的方法使用 args:

json
{
  "args": {
    "current_item": "${item}"
  }
}

或是使用 data。

json
{
  "data": {
    "current_item": "${item}"
  }
}

以上两种方法都是一样的效果,原因是在执行 action 时,会进行参数的合并,args 会合并到 data 里。

js
// \amis\packages\amis-core\src\actions\Action.ts

// 动作数据
const actionData =
  args && Object.keys(args).length
    ? omit(
        {
          ...args, // 兼容历史(动作配置与数据混在一起的情况)
          ...(afterMappingData ?? {}),
        },
        getOmitActionProp(action.actionType),
      )
    : afterMappingData;

// 默认为当前数据域
const data = actionData !== undefined ? actionData : mergeData;

console.group?.(`run action ${action.actionType}`);
console.debug(`[${action.actionType}] action args, data`, args, data);

let stopped = false;
const actionResult = await actionInstrance.run(
  {
    ...action,
    args,
    data: action.actionType === 'reload' ? actionData : data, // 如果是刷新动作,则只传action.data
    ...key,
  },
  renderer,
  event,
  mergeData,
);

而不是 setValue 中的格式。

json
{
  "args": {
    "value": { "current_item": "${item}" }
  }
}