页面交互
在一个页面中打开另一个页面,有4种方式:抽屉、对话框、嵌入页面和门户页。如下面的4幅图所示
页面和被打开的页面形成父子关系
- 在父页面中打开子页面时,可以给子页面传参
- 子页面可以给父页面返回数据
- 子页面可以给父页面发送消息
- 父页面可以给嵌入的子页面发送消息
打开子页面
子页面设置页面参数
打开子页面如果需要传参,就给子页面设置页面参数,这样在打开子页面时可以设置参数值
通过对话框打开子页面
对话框组件设置“页面文件”属性,设置为要打开的子页面,如下图所示
打开对话框时,调用“对话框”组件的“打开”操作,同时设置“页面”和“页面参数”,如下图所示
上面的操作,用代码实现时,对话框组件的“开启组件引用”属性必须设置为“是”,设置为“是”才能在 JS 文件中使用该组件。在按钮的点击事件中,开启扩展参数,将表格当前行作为事件参数,点击事件的设置如下图所示
react 代码如下
onOpenDialogBtnClick = ({row}) => (event) => {
//打开对话框并传参
this.comp("detailDialog").open({
"params": {
"id": row.fid,
"action": "edit"
}
})
}
vue 代码如下
let onOpenDialogBtnClick = ({row}) => (event) => {
//打开对话框并传参
$page.comp("detailDialog").open({
"params": {
"id": row.fid,
"action": "edit"
}
})
}
通过抽屉打开子页面
抽屉组件设置“页面文件”和“页面参数”属性,如下图所示
对话框和抽屉组件的“页面参数”属性、内嵌页面组件的“参数”属性,它们一旦绑定数据,当数据发生变化时,组件中的页面就会重新渲染。 因此,给抽屉的页面参数赋值,不要直接使用表格中显示的数据,而是单独建一个自定义数据集存储,例如本例使用“抽屉参数”数据集
打开抽屉时,先给“抽屉参数”数据集赋值,再调用“抽屉”组件的“显示”操作。
上面的操作组合,用代码实现时,抽屉组件的“开启组件引用”属性必须设置为“是”,设置为“是”才能在 JS 文件中使用该组件。在按钮的点击事件中,开启扩展参数,将表格当前行作为事件参数,点击事件的设置如下图所示
react 代码如下
onOpenDrawerBtnClick = ({row}) => (event) => {
//给“抽屉参数”数据集赋值
this.comp("drawerData").setValue("rowid",row.fid);
this.comp("drawerData").setValue("action","edit");
//调用“抽屉”组件的“显示”方法
this.comp("drawer").show();
}
vue 代码如下
let $page = usePage();
let drawerData = useData("drawerData");
let onOpenDrawerBtnClick = ({row}) => (event) => {
//给“抽屉参数”数据集赋值
drawerData.setValue("rowid",row.fid);
drawerData.setValue("action","edit");
//调用“抽屉”组件的“显示”方法
$page.comp("drawer").show();
}
通过门户页打开子页面
不需要使用组件,调用“打开页面”操作,并设置“页面源”和“参数”,如下图所示,参数的设置方法同对话框的页面参数设置。
上面的操作,改用代码实现,在按钮的点击事件中,开启扩展参数,将表格当前行作为事件参数,点击事件的设置如下图所示
代码如下,打开门户页需要多传一个title参数,作为页面标题
react 代码
onOpenPageBtnClick = ({row}) => (event) => {
//打开门户页并传参
this.navigateTo({
"url": "$UI/pcx/interactive/openPage_detail.w?id=" + row.fid + "&action=edit&title=子页面"
})
}
vue 代码
let onOpenPageBtnClick = ({row}) => (event) => {
//打开门户页并传参
$page.navigateTo({
"url": "$UI/pcx/interactive/openPage_detail.w?id=" + row.fid + "&action=edit&title=子页面"
})
}
通过内嵌页面打开子页面
关闭子页面
关闭子页面不返回数据
在子页面中调用“关闭页面”操作,或执行 this.navigateBack(); 都可以关闭子页面
关闭子页面并返回数据
返回数据集
调用“确定返回”操作,或执行 this.comp("commonOperation").okclose(数据组件id); 都可以返回数据集里面的数据并关闭子页面
例如:
react 代码
this.comp("commonOperation").okclose("selectData");
vue 代码
$page.comp("commonOperation").okclose("selectData");
对话框、抽屉、内嵌页面都可以设置“数据映射”,子页面返回的数据根据设置的数据映射关系,修改父页面中的数据。数据映射的设置,如下面两张图所示
- 选择弹出窗口(子页面)中返回的数据集
- 选择主窗口(父页面)中要修改数据的数据集
- 选中对应的列,添加映射
- 数据操作方式,有三种是新增数据,一种是修改数据,还有一种是加载数据
- 根据鉴别列新增或修改,选择主键列作为鉴别列,区分是新增还是修改。新增的数据行状态为新增,此时删除数据不会发送请求,适用于父页面保存数据的场景
- 根据鉴别列加载或修改,选择主键列作为鉴别列,区分是加载还是修改。加载的数据行状态为无,此时删除数据会发送请求,适用于子页面保存数据的场景
返回 json 数据(方法一)
执行 this.navigateBack({message:返回的数据); 注意携带 message 参数,返回数据并关闭子页面
例如:
react 代码
this.navigateBack({message:{data:{color:colors.join(",")}}});
vue 代码
$page.navigateBack({message:{data:{color:colors.join(",")}}});
返回 json 数据(方法二)
执行 this.getOpener().postMessage(返回的数据); 返回数据,执行 this.navigateBack(); 关闭子页面
例如:
react 代码
this.getOpener().postMessage({data:{color:colors.join(",")}});
this.navigateBack();
vue 代码
$page.getOpener().postMessage({data:{color:colors.join(",")}});
$page.navigateBack();
触发事件
在对话框和抽屉中调用“确定返回”操作或 okclose 方法,触发对话框和抽屉组件的确定返回事件、接收消息事件和页面的接收消息事件
在对话框和抽屉中调用 postMessage 方法,触发对话框和抽屉组件的接收消息事件和页面的接收消息事件
在对话框和抽屉中调用 navigateBack 方法,触发对话框和抽屉组件的取消返回事件、接收消息事件和页面的接收消息事件
对话框等组件的确定返回事件
在对话框和抽屉中调用“确定返回”操作或 okclose 方法,触发对话框和抽屉组件的确定返回事件。其它关闭行为,触发取消返回事件。
- 在确定返回事件中,可以获取:确定消息 message、打开时参数 params、打开页面路径 pagePath,事件参数如下图所示
- 在取消返回事件中,可以获取:打开时参数 params、打开页面路径 pagePage
例如:在子页面中使用页面加载组件,实现新增数据后,刷新父页面中的数据组件。在对话框或抽屉组件的确定返回事件中,使用写代码或操作组合均可
react 代码如下
onDetailDialogOk = (event) => {//确定返回事件
let {detail:{message, params, pagePath}} = event;
if(params.action=="create"){//判断是新增
this.comp("mainData").refreshData();//刷新数据
}
}
vue 代码如下
let $page = usePage();
let mainData = useData("mainData");
let onDetailDialogOk = (event) => {//确定返回事件
let {detail:{message, params, pagePath}} = event;
if(params.action=="create"){//判断是新增
mainData.refreshData();//刷新数据
}
}
操作组合中调用刷新操作,如下图所示
设置是否执行表达式为:确定返回.打开时参数.action 等于 create 则执行操作
双击确定返回事件中的打开时参数,再后面加上“.action”,即为获取 action 参数的值
对话框等组件的取消返回事件
在对话框和抽屉中调用“确定返回”操作或 okclose 方法,触发对话框和抽屉组件的确定返回事件。其它关闭行为,触发取消返回事件。
- 在确定返回事件中,可以获取:确定消息 message、打开时参数 params、打开页面路径 pagePath
- 在取消返回事件中,可以获取:打开时参数 params、打开页面路径 pagePage,事件参数如下图所示
对话框等组件的接收消息事件
在对话框和抽屉中调用 postMessage 方法或 navigateBack 方法,触发对话框和抽屉组件的接收消息事件。
调用 navigateBack 方法时,如果携带了 message 参数会触发两次接收消息事件,一次是接收参数消息,另一次是接收关闭消息。两次的事件参数不同,如下面两幅图所示,根据事件参数进行判断,避免代码执行多次
下图为接收参数消息的事件参数
下图为接收关闭消息的事件参数
页面的接收消息事件
在对话框和抽屉中调用 postMessage 方法或 navigateBack 方法,触发页面的接收消息事件。
调用 navigateBack 方法时,如果携带了 message 参数会触发两次接收消息事件,一次是接收参数消息,另一次是接收关闭消息。两次的事件参数不同,如下面两幅图所示,根据事件参数进行判断,避免代码执行多次
下图为接收参数消息的事件参数
下图为接收关闭消息的事件参数
发送消息
子页面给父页面发送消息
发送消息(方法一)
调用打开当前页面的对象的 postMessage 方法发送消息,对话框、抽屉、内嵌页面和门户页都可以使用
例如:
react 代码
this.getOpener().postMessage({data:"来自打开的页面消息1"});
vue 代码
$page.getOpener().postMessage({data:"来自打开的页面消息1"});
发送消息(方法二)
调用当前页面的所在页面的 postMessage 方法发送消息,对话框、抽屉、内嵌页面可使用,门户页不可以使用
例如:
react 代码
this.ownerModel?.postMessage({data:"来自打开的页面消息2"});
vue 代码
$page.ownerModel?.postMessage({data:"来自打开的页面消息2"});
父页面接收消息
页面、对话框、抽屉、内嵌页面等都有“接收消息”事件,通过对话框、抽屉、内嵌页面等组件打开的子页面发送的消息,父页面中对应组件的“接收消息”事件都会触发,同时也会触发父页面的“接收消息”事件。通过 navigateTo 打开的子页面发送的消息,会触发父页面的“接收消息”事件
在子页面中获取父页面对象
系统提供了获取父页面对象的方法,获取父页面后,可以调用父页面上的方法,但是不推荐这样使用,页面间的交互建议使用发送/接收消息的方式
react 代码
- 获取当前页面的父页面:this.ownerModel
- 获取多层页面的根页面:this.ownerPage,如果打开了多层页面,使用 ownerPage 获取最初打开的页面,通常是在门户中打开的页面
vue 代码
- 获取当前页面的父页面:$page.ownerModel
- 获取多层页面的根页面:$page.ownerPage,如果打开了多层页面,使用 ownerPage 获取最初打开的页面,通常是在门户中打开的页面
父页面给内嵌页面发送消息
获取内嵌页面中的 Page 对象
通过调用内嵌页面组件的 getInnerModel 方法获取,内嵌页面组件的“开启组件引用属性”必须设置为“是”,设置为“是”才能在 JS 文件中使用该组件,代码如下
react 代码
let innerModel = await this.comp('pageFrame0').getInnerModel;
vue 代码
let innerModel = await $page.comp('pageFrame0').getInnerModel;
给内嵌页面发送消息
调用 Page 对象的 postMessage 方法,给内嵌页面发送消息,代码如下
innerModel.postMessage({params:"发给内嵌页面的消息"});
内嵌页面接收消息
给内嵌页面发送消息后,会触发子页面的“接收消息”事件。
设置子页面标题
设置对话框标题
对话框的标题只支持文本,设置方法是:点击对话框组件的“弹出层配置”按钮,设置其中的“标题”属性
设置抽屉标题
抽屉标题支持定制,定制节点支持三种方式
- 表达式:常用选项,通过表达式定义标题文本
- 插入组件:通过插入组件形成复杂标题
- 写代码:通过写代码返回节点,形成复杂标题
点击抽屉组件的“定制标题”按钮,如下图所示,出现可编辑标题区
实现方式选择“表达式”,在属性值中输入固定值,或在表达式编辑器中输入表达式,如下图所示
页面加载组件
有一种业务场景是:列表详情。即父页面是一个列表页面,子页面是一个表单页面
- 在父页面中新增时,打开子页面,显示一个空的表单,用户填入信息后,点确定按钮,将数据返回到父页面
- 在父页面中,编辑一条数据时,打开子页面,显示这条数据的内容,用户修改后,点确定按钮,将修改的数据返回到父页面
- 在父页面中,查看一条数据时,打开子页面,显示这条数据的内容,数据只读,不允许编辑
系统提供“页面加载”组件,用于这种场景。
在子页面中添加“页面加载”组件,会给子页面添加两个参数 action 和 id
- action:动作,create 表示新增、edit 表示编辑、view 表示查看
- id:业务数据的主键,编辑和查看时,会发送请求查询这条数据
“页面加载”组件的“数据集”属性,绑定一个数据集,新增和查询都是针对这个数据集操作的。
- 当打开子页面时传入 action=create 时,“页面加载”组件会给绑定的数据集新增一条数据,这样就会显示一个空的表单页面
- 当打开子页面时传入 action=edit,id=xxx 时,“页面加载”组件会给绑定的数据集设置过滤条件:主键=xxx,并查询数据,这样就会显示一个有数据的表单页面
- 当打开子页面时传入 action=view,id=xxx 时,“页面加载”组件会给绑定的数据集设置过滤条件:主键=xxx,并查询数据。数据组件(感知上下文只读)感知到页面参数 action 等于 view 时,会设置数据只读,这样就会显示一个有数据且只读的表单页面
使用外嵌页面
对话框、抽屉和内嵌页面都是用于打开使用本系统开发出的页面(w文件),如果要打开外部页面或非本系统开发的页面(例如:Html文件),可以在 w 文件的源码中直接写 iframe 标签,即可嵌入外部页面,如下图所示。嵌入的页面即可以是 http 开头的外部页面,也可以是 UI2 目录下的文件
父页面和外嵌页面之间的发送接收消息的方式和普通网页的方式相同,示例代码如下
- 给外嵌页面发送消息
let iframe = document.getElementById('iframe0').contentWindow;
iframe.postMessage("发给外嵌页面的消息");
- 外嵌页面接收消息
window.onmessage = handleMessage;
function handleMessage(event) {
console.log(event);
}
- 外嵌页面给父页面发送消息
window.parent.postMessage('来自外嵌页面的消息');
- 父页面接收消息
constructor(props, context) {
super(props, context);
//在构造函数中绑定 onmessage 事件
window.onmessage = this.handleMessage;
}
handleMessage = (event) => {
console.log(event);
}
打开其他应用模块的页面
打开其他应用模块的页面需要通过写代码的方式,可以用navigateTo打开,代码如下: react代码
this.navigateTo({
"url":"/vuedemo/pcxapp/pcx/ddsq.w?title=订单申请"
});
vue代码
$page.navigateTo({
"url":"/'reactdemo/pcxapp/pcx/ddsq.w?title=订单申请"
});
说明
- vuedemo和reactdemo是要打开的应用模块的服务标识
- pcxapp是固定的,pcx以及后面的就是页面的在UI2目录下的路径
打开第三方页面
打开第三方页面需要通过写代码的方式,在门户中打开可以用navigateTo,url需要是打开http或https的完整路径,代码如下:
react代码
this.navigateTo({
"url":"https://www.baidu.com?title=百度"
});
vue代码
$page.navigateTo({
"url":"https://www.baidu.com?title=百度"
});
在新的浏览器页签中打开直接用window.open()就可以
案例位置
桌面-页面-页面交互-打开页面.w
桌面-页面-页面交互-子页面.w
桌面-页面-页面交互-字典多选.w
桌面-页面-页面交互-字典单选.w
桌面-页面-页面交互-嵌入页面.w