视图 controller 语法
controller 可以让前端自定义写一些代码逻辑, 可使用 ts/es6 编写。
注意:在用 getContainerByKey 时确保数据容器上没有写 id 属性,id 会覆盖当前数据容器的 key
可依赖的方法
// nusi-sdk:import { state, // 对应mobx的observable action, // 对应mobx的action computed, // 对应mobx的computed _, // 对应 lodash Controller, // Controller 基类 utils, // 工具方法 showMessage, // 显示自定义消息 PubSub, // 订阅发布} from "nusi-sdk";| 属性 | 说明 |
|---|---|
| state、action、computed | mobx 的状态管理,详情可看 mobx 文档和下方 demo |
| _ | lodash 对象,可以用 lodash 里面的任何方法: 比如 _.includes([1, 2, 3], 1); |
| Controller | 必须继承它 |
| utils | utils |
| showMessage | function showMessage(message: IMessage): Promise; |
| PubSub | 发布订阅实例 |
utils
| 方法 | 类型 | 说明 |
|---|---|---|
| openUrl | (url: string, isBlank: boolean = true) => void isBlank 默认值 为 true | 浏览器中打开连接,url 可以是外部链接,可以是应用内链接, isBlank 指定是不是另开 tab 打开 |
| getModuleApiUrl | (moduleKey: string) => string | 根据模块 key 获取后端服务对应请求服务链接 |
| triggerServerAction | (actionKey: string, data: IActionContext) => void, IActionContext | 调用 serverAction |
| confirm | (context: string) => void | 打开确认框,确认框内容是 context |
IActionContext
export interface IActionContext { modelKey?: string; record?: IDictionary | IDictionary[]; related?: IRelatedModel; env?: IDictionary; process?: string; // process action key actionLabel?: string; // for friendly log}
export interface IRelatedModel { model: string; id: string[] | string; field: string; autoGenerate?: boolean;}IMessage
| 属性名 | 类型 | 描述 |
| ------- | ------------------ | ---------------------------------------------------------------------------------------- | --------- | -------- | ----------------------------------------------------------------------------------- |
| level | “Weak” | “Strong” | 不必须,默认为 Weak, Weak 用 Toast 显示,会自动消失,Strong 用信息提示框显示,需要点确定 |
| message | string | 信息提示内容 |
| type | "Success" | "Info" | "Warning" | "Error" | 不必须,type 指定了 Strong level 时信息提示类型的。表现在信息提示内容前的图标不一样 |
PubSub
发布订阅实例
| 方法 | 参数 | 描述 |
|---|---|---|
| subscribe | (topic: string, listener: (data) => void, key?: string, followLast = false) => void | 订阅 |
| publish | (topic: string, data?: any, key?: string) => void | 发布 |
Controller 类实现了的方法和属性如下
controller 中的方法都注入到了 dsl 当做上下文,所以在 dsl 也可以直接使用
方法
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
| getContainerByKey | getContainerByKey(containerKey), containerKey: dsl 中定义在数据容器上的 key | getContainerByKey 返回值 | 获取数据容器上相关数据和方法 |
| goBack | goBack() | - | 回到上个页面 |
| triggerViewAction | triggerViewAction(action: string, { context,openViewType, env, realtedModel, payloadCallBack, modelKey }: IParam) | - | 跳转 viewAction |
getContainerByKey 返回参数
{ data: IDictionary[] | IDictionary; // 数据容器对应的数据 clearData: () => void; // 清除数据容器数据 refresh: () => void; // 刷新数据容器 updateData?: Function; // 更新数据容器数据 validateData?: (fields: string[], index?: number) => void; // 校验数据容器中的指定字段,如果是是TableForm,需指定当前行的index }triggerViewAction param 参数
{ context?: IDictionary | IDictionary[] //传入到下个页面的 context, openViewType: OpenViewType//页面打开类型, env?: IDictionary//传到下个页面的 env, relatedModel?: IRelatedModel, modelKey: string, afterClose: () => void, // 关闭页面后执行的回调 payloadCallBack: ({ modelKey?: string record?: IDictionary | IDictionary[] related?: IRelatedModel env?: IDictionary process?: string // process action key actionLabel?: string // for friendly log }) => void //payload 回调类型 }属性
| 名称 | 描述 |
|---|---|
| pageContext | 初始值为页面 search 的 key-value,可能会被覆盖 |
| i18n | i18n 相关 i18n.get(‘警告’).d(‘警告’) 带参数 i18n.get(‘fn_编辑模型’, { model: modelInfo.name }) |
Controller 生命周期
| 名称 | 说明 |
|---|---|
| pageDidLoad | 页面挂载的方法,同 react componentDidMount |
| pageDidUpdate | 会在更新后会被立即调用。首次渲染不会执行此方法。同react componentDidUpdate |
| pageUnLoad | 会在页面卸载及销毁之前直接调用, 同react componentWillUnmount |
示例
import { state, action, _, computed, Controller } from "nusi-sdk";
export default class extends Controller { @state data = [];
@computed get value() { return _.filter(this.data, ({ show }) => show); }
@action onChange() {}}典型场景
获取其他数据容器数据
<View title="用户详情"> <Detail key="user" model="user2_User"> <Fields> <Field name="name"/> <Field name="locked" /> </Fields> </Detail> <Table model="user2_Address" related="owner:user"> <Fields> <Field name="isHome" :show="getContainerByKey('user').data.locked" /> <Field name="city" /> </Fields> </Table></View>表单联动
<View title="用户地址编辑"> <Form key="user" model="user2_User" @onFieldValueChange="userFieldChange"> <Fields> <Field name="sex" /> <Field name="name" /> <Field name="age" /> <Field name="username" /> </Fields> <Actions> <Action layout="Header" logicFlow="user2_User_update" label="更新" /> </Actions> </Form> </View>import { Controller } from "nusi-sdk";
export default class extends Controller { // 当字段值发生变化时触发以下方法 userFieldChange = (fieldName: string, value: string) => { if (fieldName === "name") { // 判断当前哪个字段的值发生变化 const user = this.getContainerByKey("user"); // 根据 key 获取数据容器 user.updateData({ // 更新数据容器数据 username: value, }); } };}触发 Action
<View title="用户地址编辑"> <Form key="user" model="user2_User"> <Fields> <Field name="sex" /> <Field name="name" /> <Field name="age" /> <Field name="username" /> </Fields> <Actions> <Action layout="Header" @action="doAction" label="更新" /> </Actions> </Form></View>import { Controller, utils } from "nusi-sdk";
export default class extends Controller { doAction = ({ context }) => { // 触发 ViewAction this.triggerViewAction("actionKey", { context, modelKey: "user2_User", openViewType: "Dialog", // 默认为 Self env: { a: 1 }, }); // 触发 ServerAction utils.triggerServerAction("actionKey", { record: context, modelKey: "user2_User", env: { a: 1 }, actionLabel: "提交", // 用于log记录的名称,在xml中则是按钮文字 }); };}TableForm 联动
<View title="用户详情编辑"><Form model="user2_User" key="test"> <Fields> <Field name="name"/> <Field name="locked" /> <Field name="age" /> <Field name="code" /> <Field name="username" /> </Fields> <Actions> <Action type="Submit" label="新增" :show="!this.data.id" logicFlow="user2_User_create" after="GoBack" layout="Footer"/> <Action type="Submit" label="修改" :show="!!this.data.id" logicFlow="user2_User_update" after="GoBack" layout="Footer"/> </Actions></Form> <TableForm key="transFee" model="custom_TransFee" @onFieldValueChange="tableFormFieldChange" lookupFrom="test.transFee"> <Fields> <Field name="bus" :test="this.data" /> <Field name="airplain" /> <Field name="total" readonly /> </Fields> </TableForm></View>import { Controller } from "nusi-sdk";
export default class extends Controller { // 当字段值发生变化时触发以下方法 calcTotalFee = (rowData: any = {}) => { const { bus = 0, airplain = 0 } = rowData; return bus + airplain; }; tableFormFieldChange = (value: string, fieldName: string, index: number) => { const user = this.getContainerByKey("transFee"); // 根据 key 获取数据容器 const data = [...user.data]; // 获取这个数据容器的data const rowData = { ...data[index], total: this.calcTotalFee(data[index]) }; data.splice(index, 1, rowData); user.updateData(data); };}动态校验根据(不同情况执行不同的校验规则)
controller 里提供了 validateData(fields, index?) 函数用于校验指定字段,该函数接收 1-2 个参数: fields、index , fields 是个数组([‘field1’, ‘field2’, …])表示要去校验的相应字段,必填;只有在 tableForm 里 index 才是必须,指定当前行。
<TableForm key="qualificationLicense" @onFieldValueChange="tableFormFieldChange"> <Fields> <Field label="到期日期" name="expirationTime"> <Validations> <Validation :required="!this.record.alwaysValid || this.record.alwaysValid == 'false'" message="到期日期不能为空" /> </Validations> </Field> <Field name="alwaysValid" label="是否长期有效"/> </Fields></TableForm>expirationTime 的必填与否,取决于字段 alwaysValid 的值,所以当 alwaysValid 发生 change 的时候,要去重新校验 expirationTime 。
import { Controller } from "nusi-sdk";
export default class extends Controller { tableFormFieldChange = (value: string, fieldName: string, index: number) => { const license = this.getContainerByKey("qualificationLicense"); // 根据 key 获取数据容器 if (fieldName === "alwaysValid") { setTimeout(() => { license.validateData(["expirationTime"], index); }, 0); } };}PubSub(页面通信)
如果遇到多个页面需要通信的场景可以通过 PubSub 来解决
import { Controller, PubSub } from "nusi-sdk";
// Page Aexport default class extends Controller { constructor() { super(); this.listener = PubSub.subscribe("moduleKey/yourTopic", (data) => { // do something }); } pageUnLoad = () => { this.listener.remove(); };}
// Page Bexport default class extends Controller { onSave = (data) => { PubSub.publish("moduleKey/yourTopic", data); };}// 自定义数据容器、控件import { PubSub } from "@terminus/nusi-engine";