列表卡片单页应用缓存方案
为了解决多页应用中页面之间数据交互,平台提供了多页工程中嵌套单页应用的方案:同一功能节点间的页面若有频繁的数据交互,则可把该节点做成单页应用,同一单页应用中的数据统一在ViewModal中管理。
1. 列表卡片易用性改进需求
1.1 需要自动加载数据的应用,进入应用时,按默认快速查询方案加载数据。
1.2 卡片界面返回列表界面时:
- 从哪来回哪去:原来是哪个页签、第几页,则返回哪个页签、第几页,显示原来数据;(—-平台处理)
- 将当前列表页中清除已删除行.
- 单据列表20条数据,分两页,在第一页点删除3行后的界面效果:在列表界面第一页显示7行;若当前页数据都删除,则显示空列表界面;(—-平台处理)
- 卡片显示时如果删除了单据,返回列表时原有分页不变,去除当前页其中被删除的数据,如果列表中当前页所有行都被删除,则显示该空白页 (—-平台处理)
- 当前列表分页签情况下,做提交、审批等处理,只更新单据的状态,不在当前页签清除,也不更新页签上的数量;切换页签或点查询时,再做更新(—-页签状态领域处理)
- 批量处理时同样的效果。(—-页签状态领域自己处理)
- 卡片界面浏览态删除后,跨页翻行机制下,显示下一条单据且浏览态,如果是最后一页最后一行,则显示上一行,若无数据则显示空界面;空界面按钮只有新增类型的按钮。(—-平台提供判断条件,领域自己处理)
- 将新增数据添加在当前页最后一条后。
- 例如:单据列表查询后三条记录,一页默认显示3条,点新增,编辑后保存,点返回,回到列表界面,显示为4条记录;(—-平台处理)
- 查询后在列表界面,点击进入卡片显示后,可以下翻页到下个单据,下翻单据时是支持跨页下翻上翻的。即使翻页翻到其他分页的数据上,返回列表也是从哪来回哪去。(—-平台处理)
- 当前列表分页签情况下,新增时如何处理:新增数据添加到当前页签当前分页下,不自动更新页签上的数量,也不更新下面分页上的数据条数。(—-页签状态,领域处理)
- 例如:15条数据,一页10条,在第一页,点新增,新增了3条数据,在卡片下翻下一行,翻到最后一行,新增一条数据,返回列表第一页,则第一页显示14条;(—-平台处理)
- 分页切换时按当前数据重新分页。数据有删除时因重新分页导致的下一页可以为空白页;
- 例1:13条数据,一页显示10行,在第一页删除三条数据,切下一页时,重新分页,显示第二页为空白页,所有数据都到了第一页。(—-平台处理)
- 例2:13条数据,一页显示10行,在第一页点浏览进入卡片,切到第二页最后一行,这时点新增,保存,留在新增行的浏览态,这时候卡片中翻上一条,显示列表第一页的第10行数据,下一条是列表第二页的第一行数据。(—-平台处理)
- 页签切换时,做刷新处理,并更新各页签上数量.(—-领域处理)
2. 列表卡片适配方案
2.1 构建列表卡片单页应用
将列表卡片节点构建为一个单页应用,添加路由文件,将列表和卡片分别注册为同一个单页应用的两个节点。
单页应用的构建例子:请点击此处。
(1) 将列表、卡片组件输出 ``` SaleOrderList = createPage({})(SaleOrderList);
//删除
//ReactDOM.render(
//改为: export default SaleOrderList;
(2)增加路由文件<br /><br />(3)路由文件如下<br />_注意:路由文件asyncComponent引入的文件必须加上webpackChunkName和 /* webpackMode: "eager" / ,引入第三方库时在import里也需要加入注释 / webpackMode: "eager" */_<br /><br /><br />(4) 注意:将列表卡片改为单页应用以后,则需要分别修改列表和卡片在小应用中的对应的注册路径。<br />(a). 若列表注册路由为:"/list",则小应用注册地址为:"领域名/模块名/节点名/main/index.html#/list".<br />(b). 若卡片注册路由为:"/card",则小应用注册地址为:"领域名/模块名/节点名/main/index.html#/card".<a name="LHa03"></a>### 2.2 列表卡片改进方案前端适配步骤<a name="tb0Bu"></a>#### (1)单页应用内的页面跳转使用 pushTo若:列表的路由注册路径为"/list",卡片的路由注册路径为"/card"。<br />则:列表跳卡片代码:props.pushTo("/card",{status:"browse",id:"10990250QW"});卡片跳列表代码:props.pushTo("/list")。<br />参数的获取(getUrlParam)、设置(setUrlParam)方法不变。<a name="J8QT3"></a>#### (2) 定义单页应用缓存数据命名空间dataSource.dataSource为标识缓存数据的字符串,建议命名规范为:"领域名.模块名.节点名.自定义名"。<br />_**注意:同一单页应用中,列表和卡片的dataSource相同**。_<a name="ng59f"></a>#### (3) 列表若分页签,页签数量的更新需要领域自行处理_对于类似页签数量等非表格区的数据需要缓存的,使用(4) 方法各领域自己处理。_<a name="TOL81"></a>#### (4) 平台提供领域自己处理缓存数据API
import {cardCache} from “nc-lightapp-front”; let {setDefData, getDefData } = cardCache;
/*
- key:存储数据的key
- dataSource: 缓存数据命名空间
- data: 存储数据 */ setDefData(key, dataSource, data);
/*
- key:存储数据的key
- dataSource: 缓存数据命名空间
*/
getDefData(key, dataSource)
//表格加dataSource标识 //给表格加pkname: 表格数据的主键名字(key) createSimpleTable(“tableAreacode”,{ dataSource: dataSource, pkname: pkname, componentInitFinished:()=>{<a name="isC61"></a> #### (5) 列表适配步骤 _**(5.1) 给列表表格(createSimpleTable)增加dataSource标识**_
} })//缓存数据赋值成功的钩子函数 //若初始化数据后需要对数据做修改,可以在这里处理
let { hasCacheData } = this.props.table;**_(5.2) 卡片页面返回列表页面(初始化)时,先判断是否已经存在缓存数据,若存在缓存数据,则不需要重新查询给表格赋值,否则发起查询请求,加载表格数据._**_ 注意:查询和刷新按钮需要重新查询,请求后台数据。_
/*
- dataSource: 缓存数据命名空间
*/
if(!hasCacheData(dataSource){
ajax({
}) }url:"...", data:"...", success:(res)=>{ if(res && res.data && res.data["tableAreacode"]){ this.props.table.setAllTableData(res.data["tableAreacode"]); } }
let {deleteCacheId} = this.props.table;**_(5.3) 删除列表表格数据时,删除成功后,需要调用平台方法deleteCacheId,其他处理逻辑不变_**
//删除成功后, 调用该方法删除缓存中对应id
/*
- tableAreacode:表格区域编码
- pkvalue:数据主键的值
*/
deleteCacheId(tableAreacode,pkvalue);
let {addCacheId} = this.props.table; //新增成功后, 调用该方法新增缓存中对应id**_(5.4) 新增列表表格数据时,新增成功后,需要调用平台方法addCacheId,其他处理逻辑不变_**
/*
- tableAreacode:表格区域编码
- pkvalue:数据主键的值
*/
addCacheId(tableAreacode,pkvalue);
//翻页组件加dataSource标识 createCardPagination({ handlePageInfoChange: ()=>{}, dataSource: dataSource })<a name="mSWBj"></a> #### (6)卡片适配步骤 _**(6.1) 给翻页组件cardPagination添加dataSource标识**_
import {cardCache} from “nc-lightapp-front”; let { getCacheById, updateCache } = cardCache;**_(6.2) 卡片翻页查询数据时,先判断是否有缓存数据,若是,取缓存数据给卡片赋值;否则,发起查询请求,并把请求回来的数据更新到缓存中_**
/*
- id:数据主键的值
- dataSource: 缓存数据命名空间 */ let cardData = getCacheById(id, dataSource);
if(cardData){ this.props.form.setAllFormValue({“formAreacode”:cardData.head[“formAreacode”]}); this.props.cardTable.setTableData(“tableAreacode”,cardData.body[“tableAreacode”]); }else{ //发起ajax请求查询数据 ajax({ url:, data:, success:(res)=>{ //给界面组件赋值
/*
* idname: 数据主键的命名
* id:数据主键的值
* headAreacode: 卡片表头的区域编码
* dataSource: 缓存数据命名空间
*/
updateCache(idname,id,res.data,headAreacode,dataSource);
}
})
}
**_(6.3) 在列表点新增或在卡片上点新增按钮后,新增保存时,保存成功后,需要调用addCache方法,将数据存储到缓存中_**
import {cardCache} from “nc-lightapp-front”; let { addCache } = cardCache;
ajax({ url:, data, success:(res)=>{ //将返回数据赋值到界面上
//将返回数据存储到缓存中
/*
* id:数据主键的值
* headAreacode: 卡片表头的区域编码
* dataSource: 缓存数据命名空间
*/
addCache(id,res.data,headAreacode,dataSource);
//另外还需要设置下卡片翻页组件的当前id
this.props.cardPagination.setCardPaginationId({id: id})
}
})
**_(6.4) 卡片上点击新增按钮后,未保存,又点了取消按钮, 则需调用方法getCurrentLastId,获取当前列表最后一条数据渲染界面_**
import {cardCache} from “nc-lightapp-front”; let {getCurrentLastId } = cardCache;
let id = getCurrentLastId(dataSource);
//根据id获取下条数据:取下条数据时也要同第2步一样,先从缓存中取,缓存里没有再发数据请求。
**_(6.5) 卡片修改保存时,保存成功后,需要调用updateCache方法,将数据更新到缓存中_**
import {cardCache} from “nc-lightapp-front”; let { updateCache } = cardCache;
ajax({ url:, data, success:(res)=>{ //将返回数据赋值到界面上
//将返回数据存储到缓存中
/*
* idname: 数据主键的命名
* id:数据主键的值
* headAreacode: 卡片表头的区域编码
* dataSource: 缓存数据命名空间
*/
updateCache(idname,id,res.data,headAreacode,dataSource);
}
})
**_(6.6) 在卡片删除数据时,删除成功后,先通过getNextId获取下条数据的主键,再调用deleteCacheById方法,将缓存数据删除_**
import {cardCache} from “nc-lightapp-front”; let { getNextId, deleteCacheById } = cardCache;
ajax({ url:, data, success:(res)=>{ //删除成功!
let id = this.props.getUrlParam("id");
//根据当前id,获取下个id
/*
* id:数据主键的值
* dataSource: 缓存数据命名空间
*/
let nextId = getNextId(id, dataSource);
//调用删除缓存数据方法
/*
* idname: 数据主键的命名
* id:数据主键的值
* dataSource: 缓存数据命名空间
*/
deleteCacheById(idname,id,dataSource);
//根据nextId查询下条数据
//注意:查询下条数据时,也同样需要先判断有没有缓存数据,没有缓存数据时,再发查询请求。
//----
}
})
**_(6.7) 点击翻页组件时,拿到新的id也要先判断是否存在对应的缓存数据,若存在,则取缓存数据给界面赋值;否则,发ajax请求查询数据,并将查询回的数据更新到缓存中_**
import {cardCache} from “nc-lightapp-front”;
export default function (props, pk) { let { getCacheById, updateCache } = cardCache; props.setUrlParam(pk); /*
* id:数据主键的值
* dataSource: 缓存数据命名空间
*/
let cardData = getCacheById(id, dataSource);
if(cardData){
this.props.form.setAllFormValue({"formAreacode":cardData.head["formAreacode"]});
this.props.cardTable.setTableData("tableAreacode",cardData.body["tableAreacode"]);
}else{
//发起ajax请求查询数据
//给界面组件赋值
/*
* idname: 数据主键的命名
* id:数据主键的值
* headAreacode: 卡片表头的区域编码
* dataSource: 缓存数据命名空间
*/
updateCache(idname,id,headAreacode,dataSource);
}
} ```
