Skip to content

data-list-manager

一、场景和形态

对UI、交互、数据进行高级封装的组件,提供完整的数据列表生命周期管理。数据组件边界颇多,要特别注意数据类型转换问题,目前建议统一使用字符串维护组件数据。

现场演示

下面这个界面,是由axue-data-list-manager组件渲染

演示代码如下:

html
<!--在vitepress中的.md文件中直接引入下面的代码-->
<div id="container"></div>
<script setup>
  import('axue').then(({showTip}) => {
    const componentName ='axue-data-list-manager'
    const el = document.createElement(componentName);
    let data =[{
        prdId:1,
        title:"傲雪项目",
        corp:"傲雪公司",
        owner:"傲雪",
        tel:"17788889999",
        createTime:"1700364852738",
    },{
        prdId:2,
        title:"青松项目",
        corp:"青松公司",
        owner:"青松",
        tel:"14455556666",
        createTime:"1700364852738",
        axueMarking:{            //组件支持的特殊条级标记
            notDelete:true,      //表示该行不能删除
            status:"正常",         //状态名
            statusType:"nomal"    //正常
        }
    }]
    let args={
        caption:"我的项目",
        addText:"添加项目",
        dataType:{    //定义特殊的字段类型,对应有处理机制
            "prdId":"number",
            "tel":"telephone",
        },
        idField:"prdId",    //指明索引字段,必须有
        showFieldInList:["title","corp"],                 //列表中要显示的字段范围
        showFieldInAdd:["corp","owner","tel"],            //新增页要显示的可输入字段范围,如果包含索引字段,则表示允许用户填
        showFieldInUpdate:["corp","owner","tel"],         //编辑页要显示的可修改字段范围,如果包含索引字段,则表示用户可修改
        showFieldInDetail:["corp","owner","tel"],         //详情页要显示的字段范围,默认全部。
        dataMarking:{    //定义特殊的字段,使用标识进行业务分类
            classifyField:"xx",
            icon:"XXurl"
        },
        onAddRow(dataListManager,rowdata){
            console.log("onAddRow回调:",rowdata, dataListManager)
            //接下来处理数据同步和修正的正异常逻辑
        },
        onUpdateRow(dataListManager,rowdata){
            console.log("onUpdateRow回调:",rowdata, dataListManager)
            //接下来处理数据同步和修正的正异常逻辑
        },
        onDeleteRow(dataListManager,rowdata){
            console.log("onDeleteRow回调:",rowdata, dataListManager)
            //接下来处理数据同步和修正的正异常逻辑
        },
        onClickRow(dataListManager,rowdata){
            console.log("onClickRow回调:",rowdata, dataListManager)
            //接下来处理数据同步和修正的正异常逻辑
        },
        onPulldown(dataListManager){
            console.log("onPulldown回调:",dataListManager)
            //接下来处理数据同步和修正的正异常逻辑
        },
    }
    //对于行级操作,如果内置的删除、编辑功能不够,可以通过extendFunc参数进行功能扩展
    let extendFunc=[
        {
            label:"访问文件夹",
            onClick:function (){}
        }
    ]
    el.args = args
    el.data=data
    el.extendFunc=extendFunc
    document.getElementById('container')?.appendChild(el);
  });
</script>

二、使用方式

使用组件

HTML
<axue-data-list-manager 
    .args=${args} 
    .data=${data}  
    .extendFunc=${extendFunc} 
></axue-data-list-manager>

需要定义并传入三类参数:属性、数据、菜单扩展,其中extendFunc可以不传,则默认对每一行内置提供了编辑和删除两个功能,下面依次说明。

定义属性

需要遵循数据定义规范

JavaScript
//分别定义数据实例和数据结构
let data =[{
        prdId:1,
        title:"傲雪项目",
        corp:"傲雪公司",
        owner:"傲雪",
        tel:"17788889999",
        createTime:"1700364852738",
    },{
        prdId:2,
        title:"青松项目",
        corp:"青松公司",
        owner:"青松",
        tel:"14455556666",
        createTime:"1700364852738",
        axueMarking:{            //组件支持的特殊条级标记
            notDelete:true,      //表示该行不能删除
            status:"正常",         //状态名
            statusType:"nomal"    //正常
        }
    }
]
let args={
    caption:"我的项目",
    addText:"添加项目",
    dataType:{    //定义特殊的字段类型,对应有处理机制
        "prdId":"number",
        "tel":"telephone",
    }
    idField:"prdId",    //指明索引字段,必须有
    showFieldInList:["title","corp"],                 //列表中要显示的字段范围
    showFieldInAdd:["corp","owner","tel"],            //新增页要显示的可输入字段范围,如果包含索引字段,则表示允许用户填
    showFieldInUpdate:["corp","owner","tel"],         //编辑页要显示的可修改字段范围,如果包含索引字段,则表示用户可修改
    showFieldInDetail:["corp","owner","tel"],         //详情页要显示的字段范围,默认全部。
    
    dataMarking:{    //定义特殊的字段,使用标识进行业务分类
        classifyField:"xx",
        icon:"XXurl"
    }
    
    onAddRow(dataListManager,rowdata){
        console.log("onAddRow回调:",rowdata, dataListManager)
        //接下来处理数据同步和修正的正异常逻辑
    },
    onUpdateRow(dataListManager,rowdata){
        console.log("onUpdateRow回调:",rowdata, dataListManager)
        //接下来处理数据同步和修正的正异常逻辑
    },
    onDeleteRow(dataListManager,rowdata){
        console.log("onDeleteRow回调:",rowdata, dataListManager)
        //接下来处理数据同步和修正的正异常逻辑
    },
    onClickRow(dataListManager,rowdata){
        console.log("onClickRow回调:",rowdata, dataListManager)
        //接下来处理数据同步和修正的正异常逻辑
    },
    onPulldown(dataListManager){
        console.log("onPulldown回调:",dataListManager)
        //接下来处理数据同步和修正的正异常逻辑
    },
}

//对于行级操作,如果内置的删除、编辑功能不够,可以通过extendFunc参数进行功能扩展
let extendFunc=[
    {
        label:"访问文件夹",
        onClick:function (){}
    }
]

注入事件回调

下拉回调

JavaScript
/**
    如果数据是分批提供的,需要处理增量逻辑
*/

function onPulldown(dataListManager ){    //传入当前组件对象,用于刷新数据
    //接下来处理业务
    //获取当前组件数据的尺寸
    const lenght = dataListManager.data.lenght
    const pageSize = 10
    const page=lenght/10
    
    //模拟异步请求,实际应用中应该调用后端接口
    const response = await fetch(`https://api.example.com/data?page=${page}&pageSize=${pageSize}`);
    const newData = await response.json();
    
    // 将获取到的新数据添加到组件的数据中
    dataListManager.data = [...dataListManager.data, ...newData];
}

新增回调

JavaScript
/**
    前端--服务端的数据同步链路过程,组件不关心
    回调前,内存数据已经提前做了新增
    如果同步错误,需要开发者在回调中特别处理数据数据
    特别注意:
        为了精准渲染性能,新增时,即便不指定可编辑id,组件也会生成一个唯一的临时id
        如果数据的实际id是由后端生成的,或者前端其他规则生成的,也需要在回调中特别处理
*/
function onAddRow(dataListManager,rowdata){
        console.log("onAddRow回调:",rowdata, dataListManager)
        //接下来处理数据同步和修正的正异常逻辑
}

更新回调

JavaScript
/**
    更新增一样,但只需要特别处理数据同步的正异常逻辑
*/
function onUpdateRow(dataListManager,rowdata){     //传入用户新增的一条数据
    //接下来处理数据同步的逻辑 
}

删除回调

JavaScript
/**
    更新增一样,但只需要特别处理数据同步的正异常逻辑
*/
function onDeleteRow(dataListManager,rowdata){     //传入用户新增的一条数据
    //接下来处理数据同步的逻辑 
}

点击数据条的回调

JavaScript
/**
    如果不定义点击回调,则默认会打开组件的详情查看页
    注意,如果定义了回调,则不再打开详情页,这是二选一的设计
*/
function onClickRow(dataListManager,rowdata){  //传入用户点击的那一条数据
    //接下来处理跳转逻辑
}

属性项

内联属性说明类型默认值
caption列表标题,显示在列表左上方string"我的列表"
addText新增组件的文本string"添加"
isBorderDivide数据表格和标题之间是否显示线条间隔,一般在不显示数据表格边框时使用boolfalse
isShowTableBorder数据表格是否显示边框boolfalse
isClickRowShowDetail是否点击一条数据时,进入详情页。该配置如果存在与否,不影响@clickRow事件回调booltrue
idField一条数据的唯一索引字段,增删交互必备stringnull
showFieldInList列表中要显示的字段范围。 注意,列表宽度限制,一般不超过4个array[]
showFieldInAdd新增页要显示的可输入字段范围。注意,如果不包含索引字段,则表示索引允许用户填,会自动生成一个uuid占位array[]
showFieldInUpdate编辑页要显示的可修改字段范围。 注意,如果不允许用户修改索引,则不要包含索引字段array[]
showFieldInDetail详情页要显示的字段范围,默认全部booltrue,默认自动生成uuid。 但对于数字类型的id,会被忽略
dataType数据处理类型定义集:默认所有涉及字段都采用文本处理方式,如果不是,则应以字段名:处理类型进行申明
number数字function会自动转为字符串显示,更新时回传数字
image图片function会将值视为src
telephone电话function新增编辑都需要走认证流程交互
file文件function支持上传修改交互
事件回调注册,回调入参详见范例,正常是第一个参数是组件本身,row级方法第二个参数会传入行数据
onAddRow新增页面回调,返回用户新建的一条数据对象functionnull
onPulldown列表页面下拉回调,要求开发者主动提供更多数据,并刷新列表数据对象functionnull
onUpdateRow编辑页面回调,返回用户更新后的一条数据对象functionnull
onDeleteRow列表页面删除回调,返回被删除的数据idfunctionnull
onClickRow列表页面点击一条数据的回调,返回被点击的数据idfunction默认会进入单条数据详情页。如果有回调,则会替换默认行为

数据API

传入的数据,最终会被组件结合dataStruct定义来进行解析

内联属性说明类型默认值
data组件实际维护的数据列表, 每一个数据项均以{key:value}表示,只支持number、bool、string基础类型array[]

框架数据标记规范

对任一条data数据,框架支持标准的框架标记

内联属性说明类型默认值
axueMarking一个对象,标准字段如下array[]
notDelete表示该行不能删除booltrue
status状态名stringnull
statusType状态类型,影响标识颜色: "nomal", 正常,显示为绿色"warning", 警告,显示为黄色"grey", 淡化,显示会灰色string"nomal"

扩展属性API

对于一行数据,省略号弹出,内置了删除、编辑两个功能菜单,如果不够,可以自定义扩展

内联属性说明类型默认值
extendFunc扩展功能列表, 每一个功能均满足以下标准结构array[]
label菜单名string"自定义功能"
onClick点击回调,将传入rowdata数据functionnull

示例

JavaScript
/**
    定义回调时,应该定义rowdata入参,组件会自动传入
    注意,允许你在定义回调时,无入参,组件会照传,但不应该定义更多的参数,因为组件只会传入被点击的行数据
    如果确实有多参数需求,请写在函数体内
*/
function onClick (rowdata){
    console.log(rowdata)
}

特别说明

数据管理组件,需要特别注意的是数据规范和同步。

关于数据规范

传参机制:

  • 允许服务端传冗余数据
  • 对于新增页、编辑页、列表,要求定义可编辑、可显示范围
  • 对于详情页字段,允许不定义,如果不定义,默认会显示该条数据的所有字段
  • 正常不应该出现列表的各个数据长度不一致的情况
  • 因为涉及了精准删除和性能考量,id索引字段是必须字段,且应该唯一。由于必须规则,即使定义了不填写索引字段,新增页也会自动生成一个临时的。这需要在收到回调后特别处理,完成替换。
  • 更精细的行级控制,由组件的行级标记语法支持,比如禁止某一行被删除,强化状态或分类区分

关于数据同步

callback设计机制:

  • 新增、更新、删除时,内存维护的data数据会第一时间更新,再回调通知开发者。
  • 开发者应该在回调逻辑中,异步处理和读写存储服务层的同步
  • 如果服务层处理异常,前端在异步逻辑的回调中,要重新处理边界,比如tips提醒用户、重置内存数据等

关于数据处理类型

dataType用于定义组件内部对一个数据的处理机制,代表了组件的业务支持能力范围,先从文本开始,逐渐上线。这也是一个通用规范,是label-content的一致规范,也是是label-*系列组件的适配范围设计基石。

说到底,数据组件的编辑能力建立在label-*系列组件之上。

青锋三尺,樵夫十年