页面组件
每个页面有且只有一个页面组件,作为页面结构的根,往其上添加各种组件,形成完整的页面。
组件定义
- 桌面端 React:UI2/comp/antdpro/components/Page/Page.react.js
- 移动端 React:UI2/comp/vantui/components/Page/Page.react.js
- 桌面端 Vue :UI2/comp/antdv/components/Page/Page.vue
- 移动端 Vue :UI2/comp/vant/components/Page/Page.vue
组件属性
页面组件提供以下这些属性
属性 | 属性名 | 作用 |
---|---|---|
禁用加载效果 | disableLoading | 页面显示时不显示加载遮罩 |
自动充满 | isFullPage | 页面显示时页面高度是否自动撑满 |
继承 | extends | 设置页面结构从哪个页面继承,设置后,被继承页面修改,当前页面也会修改 |
状态 | state | 存储页面状态,通过 this.setState 赋值,通过 this.state 取值 |
自动充满
页面背景色默认是透明的,设置为白色后,可看到自动充满的效果
- 不自动充满如下图所示
- 自动充满如下图所示
页面参数
无论是否设置页面参数,打开页面时在 url 上添加参数,在页面中通过 this.params 都可以获取到参数。那么,为什么要设置页面参数呢?
原因有以下两点:
- 低代码开发:在页面设计时,设计器只能列出设置的页面参数,列不出未设置的页面参数;
- 页面自完整:当页面参数很多时,还需要配合其它文档,才能了解页面参数,如果设置了页面参数,只需查看页面参数即可
案例参考页面交互
页面继承
页面继承用于多个页面基本相同,只有少量不同,且编辑一个页面后,其他页面也需要得到同样修改的场景。
普通页面包括完整的页面结构,而继承页面由两部分组成:
- 被继承页面:包括完整的页面结构,作为继承页面的基础页面结构
- 继承页面:包括与被继承页面的差异,作为继承页面的补充页面结构
页面编译时,将上面两部分合并为一个页面。
添加继承页面
添加继承页面的做法是
- 添加页面时选择“页面继承”模板,从现有页面中选择一个作为父页面,作为被继承页面
- 在设计页中编辑页面,例如:添加、删除组件、修改组件属性等
此时“源码”页中显示的是父页面和继承页面合并后的代码,用于页面设计,不要手工修改。切换到“代码”视图,可以看到合并后的代码文件,如下图所示
下图才是继承页面的源码,这里只记录和父页面的差异
JS 的继承
在 JS 文件中重写父页面中的方法,这个重写的 js 方法会覆盖父页面中的方法。例如在继承页面中重写页面显示事件,代码如下图所示
在 vue 页面中使用 state
定义 state
使用 reactive 定义 state 中的属性及初始值
let state = reactive({aa:"1"});
页面显示 state
使用一个大括号引用 state 的属性
<antdv:Typography.Text content="{state.aa}" id="typographyText5">
</antdv:Typography.Text>
js 赋值 state
直接给 state 的属性赋值
let onSetValueBtnClick = (event) => {
state.aa = 2;
}
双向绑定 state
系统 input 组件
使用 v-model_ 声明属性双向绑定,属性值使用两个个大括号引用 state 的属性
<antdv:Input id="input2" v-model_value="{{state.aa}}">
</antdv:Input>
原生 input 组件
引用原生组件,并重命名(不重命名使用的还是系统组件),定义一个渲染方法,使用 jsx 语法返回原生组件代码
import {Input as Input2} from "ant-design-vue";
let inputRender = () => {
return <Input2 v-model:value={state.aa}></Input2>
}
在 w 文件的适当位置,使用一个大括号引用渲染方法
{inputRender()}
组件方法
页面组件提供以下这些方法
方法 | 作用 | 说明 |
---|---|---|
comp(key) | 获取组件的 js 对象,以便调用组件的方法 | key 是组件的 id 或 ref |
navigateTo(params) | 打开页面 | params.url 是要打开页面的 url,需要携带 title 参数作为页面标题,例如:$UI/pcx/page/yemian_jc.w?title=页面继承;params.executor 是传入页面的执行者,用于页面中的上下文组件获取当前人员成员信息 |
navigateBack(object = {}) | 关闭页面 | 写 object.message 参数,在关闭页面后,会触发父页面的接收消息事件 |
setState(params) | 设置页面状态 state,除了系统的 loading 和 data,也可以设置自己的 state | 例如:设置 state 中的 loading 显示和隐藏遮罩,this.setState({loading:true}); |
isReadonly() | 根据页面 url 中的参数,判断当前页面是否只读 | 以下4种情况表示只读:页面参数 _pagePattern 等于 readonly 时;页面参数 activity-pattern 等于 detail 时;页面参数 readonly 等于 true 时;页面参数 action 等于 view 时 |
getParentFrame() | 作为内嵌页面,获取父页面 | |
getServiceUrl(url, serviceName) | 获取服务请求的完整路径 | url 是服务请求的url,例如:/main/dbrest/orderm;serviceName 是应用名 |
getUIUrl(url) | 获取页面编译后的 url | url 是设计时页面文件路径,例如:$UI/pcx/page/yemian_jc.w |
getParentPath() | 设置使用父路径后,获取当前父路径 | |
getServiceName() | 获取当前应用名 | |
request | 发送请求 | 参考[前端调用服务] |
i18n(key,import.meta.url) | 获取当前语言对应的资源 | 参考[多语言配置] |
页面生命周期
页面组件提供了页面的生命周期,在不同的时刻派发相应的事件。下图说明了页面 Page 实例的生命周期(以 /entry/mobile/work.w 为例)
打开页面过程说明
- 加载页面资源文件 → 创建组件 → loading=true(显示加载遮罩)→ 派发 onLoad 事件
- 下面开始两条线并行
- 加载自动加载的数据 → 派发 onInitState 事件(加载用户数据)→ loading=false(隐藏加载遮罩)
- 显示页面切换动画(用时300ms)→ 派发 onShow 事件
- 上面两条线完成,渲染页面 → 派发 onReady 事件
图形说明
- 上图中提到的数据组件,泛指不可视组件,包括数据集组件(restData)、服务请求组件(serviceRequest)、上下文组件(context)等
- 注意上图中 loading 的变化,loading 等于 true 时,页面会有默认遮罩加载效果,可通过 this.state.loading 获取 loading 的值
组件事件
页面组件提供以下这些事件,这些事件和生命周期不同,均是回调事件
事件 | 事件名 | 作用 |
---|---|---|
页面加载 | onLoad | 自动加载的数据未准备好 |
数据初始化 | onInitState | 自动加载的数据已准备好,可执行用户的加载数据代码,返回值会作为状态数据 |
显示 | onShow | 页面显示时触发 |
初次渲染完成 | onReady | 自动加载的数据和用户加载的数据都已准备好,页面显示事件已执行完成 |
接收消息 | onMessage | 收到消息时触发 |
隐藏 | onHide | 打开其他页面时触发 |
卸载 | onUnLoad | 关闭当前页面时触发 |
Ref 变化 | onReactRefChanged | 组件的 ref 属性值改变后触发,即设置了 ref 属性的组件渲染后触发 |
数据初始化事件 onInitState 是页面组件提供的事件,旨在统一管理数据的初始化,即不论是自动加载的数据,还是用户写代码加载的数据,都属于数据初始化。当数据初始化开始时,显示页面加载遮罩,当数据初始化完成时,关闭页面加载遮罩。
数据初始化事件不仅用于加载用户数据,返回值会写入 state。作为状态数据。示例代码如下:
onPageInitState = async (event) => {
let serviceInfo = await this.request({
url: "/manager/services/info"
});
return serviceInfo.data;
}
在 onReady 事件中,执行 console.log(this.state);可看到 state 的内容,如下图所示
其中
- loading 和 data 是平台使用的 state 部分
- loading 表示页面的 loading 状态
- data 包括页面不可视组件的状态,展开后如下图所示
- name 和 label 是数据初始化事件的返回值,写入了 state
自定义加载遮罩
当页面的 this.state.loading 为 true 时,系统自动显示遮罩,桌面端显示 Spin,移动端显示 Loading。重载页面组件的 setDefaultLoading 方法自定义加载遮罩
react 自定义加载遮罩
在 common.js 中自定义加载遮罩的全局修改方案。按照标准 react 逻辑渲染,当页面的 this.state.loading 为 true 时,执行 Page.setDefaultLoading 方法,其中参数 props 包括 pagePath 以及当前页面的 props,可以据此做出不同页面的骨架屏方案
移动端自定义加载遮罩,UI2/mobile/common.js 代码如下
import React,{Fragment} from 'react';
import {Skeleton} from '@antmjs/vantui';
import Page from '../comp/vantui/components/Page/Page.react';
import "./common.css";
Page.setDefaultLoading((props)=>{
let pagePath = props.pagePath;
return <Fragment>
<div className={'x-none-background'}></div>
<Skeleton title={true} avatar={true} row="3" className={'x-none-background'}/>
</Fragment>
})
桌面端自定义加载遮罩,UI2/pcx/common.js 代码如下
import React,{Fragment} from 'react';
import {Skeleton} from 'antd';
import Page from '../comp/antdpro/components/Page/Page.react';
import "./common.css";
Page.setDefaultLoading((props)=>{
let pagePath = props.pagePath;
return <Fragment>
<div className={'x-none-background'}></div>
<Skeleton active className={'x-none-background'}/>
</Fragment>
})
UI2/mobile/common.css 和 UI2/pcx/common.css 代码相同,代码如下
:global{
.x-none-background{
clear: both;
opacity: 1;
user-select: none;
pointer-events: none;
background: white;
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
}
vue 自定义加载遮罩
和 react 不同,vue 的 jsx 代码必须写到 xxx.vue.jsx 文件中,因此不能在 common.js 文件中,实现统一的自定义加载遮罩,在需要自定义遮罩的页面的 js 文件中自定义加载遮罩方案。按照标准 vue 逻辑渲染,当页面的 this.state.loading 为 true 时,执行 Page 组件的 setDefaultLoading 方法,其中参数 props 包括当前页面的 props
移动端自定义加载遮罩,UI2/mobile/页面的 js 文件代码如下
import {setDefaultLoading} from '$UI/comp/vant/components/Page/Page.vue';
import { Skeleton } from 'vant';
setDefaultLoading((props)=>{
let pagePath = props.pagePath;
return <Fragment>
<div class={'x-none-background'}></div>
<Skeleton title row="3" class={"x-none-background"}/>
</Fragment>;
})
let $page = usePage();
桌面端自定义加载遮罩,UI2/pcx/页面的 js 文件代码如下
import {setDefaultLoading} from '$UI/comp/antdv/components/Page/Page.vue';
import { Skeleton } from 'ant-design-vue';
setDefaultLoading((props)=>{
let pagePath = props.pagePath;
return <Skeleton active class={"x-none-background"}/>;
})
let $page = usePage();
样式定义在 UI2/mobile/common.css 或 UI2/pcx/common.css 中,样式代码相同,代码如下
.x-none-background{
clear: both;
opacity: 1;
user-select: none;
pointer-events: none;
background: white;
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
页面自动引用 common.js,在 common.js 文件中引用 common.css,每个页面就自动引用了 common.css 文件,common.js 代码如下
import './common.css';
案例位置
桌面-页面-页面-页面组件.w
桌面-页面-页面-使用state.w
桌面-页面-页面-页面继承.w
桌面-页面-页面-返回消息.w
桌面-页面-页面-骨架屏.w