阅读视图

发现新文章,点击刷新页面。

Luckysheet 远程搜索下拉 控件开发 : 揭秘二开全流程

前言

远程搜索下拉控件是非常常见的控件,应用在表单填写场景下,也是非常合适的,本例将带领大家实现以下效果,并真实了解并熟悉 luckysheet 的二开流程。

在这里插入图片描述

拓展单元格属性

在官网上,有一个常见问题,既然已知批注是直接加到单元格属性上,那么,我们拓展属性,是不是可以参考批注的实现方案?

在这里插入图片描述 我们设定以下是远程搜索下拉的单元格拓展属性:

// 扩展后的单元格对象
const cell = {
    v: null, // 原始值
    m: null, // 显示值
    ct: { fa: "General", t: "s" },
    // ... other properties

    // 新增远程搜索下拉配置
    remoteSelect: {
        // 是否启用远程搜索,[必传]
        enable: boolean,

        // 用户输入时的回调函数,用于获取远程数据
        onInput(value): Promise<Array<string>> {
            // 这个函数需要返回一个Promise对象,resolve一个数组,数组的元素为下拉选项对象
        }

        // 用户选定某个选项后的回调函数
        onSelect(item): void {
            // item 为用户选定的选项对象,值是onInput函数返回的数组中的某个元素
        }

        // 是否需要设定当前输入单元格的值 [可选]
        setValue(item): string{
           // item 为用户选定的选项对象,需要返回一个字符串,用于设定单元格的值
        },

        // 自定义类名  [可选]
        popperClass: string,
    },
};

何时触发?

在这个场景中,我们需要在用户输入值时,进行远程数据获取,渲染列表,因此,需要在用户进行编辑时,进行处理:

  1. 一个方案,是在初始化 inputHTML 时,将相关事件处理: 在这里插入图片描述
 $("body").append(inputHTML)
 // 进行相关事件绑定: [伪代码]
 $input.on('input',function(){
 // 这里是未知具体单元格信息的,需要通过外部传递
 const remoteSelectOptions = Store.flowdata[r][c]
 // 执行后续操作
 })
  1. 另一个方案,是用户双击时,唤起输入框后,进行判断:
// handler.js
$("#luckysheet-cell-main, #luckysheetTableContent").dblclick(function(){
// 这个函数是内置的哈,因此,可以直接获取到 r c
// 判断当前单元格是否需要初始化远程搜索控件
RemoteSelect.checkCellNeedRemoteSelect(row_index, col_index)
})

两种方案我都试过了,实现略有不同,但都可以实现,还是借助原生的 dblclick 好处理些。

校验远程搜索下拉

既然每一个单元格双击,都会触发这个校验,那么何时才需要初始化这个下拉框呢?

// 判断当前单元格是否需要显示下拉框
checkCellNeedRemoteSelect: function(r, c) {
    // 通过 r c 获取单元格信息
    let cell = Store.flowdata[r][c];

    // 如果 cell 没有配置 remoteSelect 或者 remoteSelect.enable 为 false 则返回
    if (!cell || !cell.remoteSelect || !cell.remoteSelect.enable) {
        return;
    }
}

检验完成后,如果需要初始化校验,别忘了, 我们底层还要监听输入框事件哈:

// 不然,开始监听 input 输入事件
$("#luckysheet-input-box .luckysheet-cell-input").off("input").on("input", function() {
        let value = $(this).text().trim(); // 获取用户输入的值
      
        if (cell.remoteSelect && cell.remoteSelect.onInput && typeof cell.remoteSelect.onInput == "function") {
            // 调用外部接口
            cell.remoteSelect
                .onInput(value)
                .then(function(dataList) {
                    $this.loading = false;
                    $this.showRemoteSelect(dataList);
                })
                .catch((error) => {
                    $this.loading = false;
                    $this.hideRemoteSelect();
                    console.log("请求接口错误", error);
                    tooltip.info('<i class="fa fa-exclamation-triangle"></i>', "接口请求失败");
                });
        }
    });

初始化下拉框

远程搜索的核心,就是下拉选项,当远程接口初始化完成后,执行如下:

dataList.forEach((item) => {
const $item = $(`<div class="${this.selectItemClass}">`)
.text(item)
.click(() => {
// 触发选择回调
if (cell.remoteSelect && cell.remoteSelect.onSelect && typeof cell.remoteSelect.onSelect === "function") {
    cell.remoteSelect.onSelect(item);
}
})

这里就一个难点要处理,如何将下拉框定位到输入框的位置:

// 这里采用巧方案,直接取输入框的位置
const $input = $("#luckysheet-input-box");
const left = parseInt($input.css("left")) || 0;
const top = parseInt($input.css("top")) || 0;

// 获取当前单元格的高度 行高
const [_row_pre, rowHeight] = rowLocation(this.r);

// 设置下拉框位置和宽度
$selectBox.css({
    top: `${top + rowHeight + 4}px`, // 在单元格下方显示
    left: `${left}px`,
});

总结

虽然代码看起来不复杂,但是了解luckysheet 的源码、实现思路,以及单元格拓展实现方案是非常重要的。

通过本次实现,我们初步了解了luckysheet的二次开发流程,在不破坏原有功能的基础上添加新特性。远程搜索下拉控件的实现展示了如何在现有表格组件基础上,通过合理的架构设计和代码组织,添加复杂交互功能。

❌