在数据库中实现 js 与 Sprig 模板的交互

在数据库中实现 js 与 Sprig 模板的交互

see https://ld246.com/article/1734002304855

在数据库模板中可以利用img标签实现 js 与 Sprig 模板的交互,利用 js 来处理数据,就更方便了。

比如:

.action{$blocks := queryBlocks "select * from blocks limit 1"}
<span><img src="" data-result='.action{toJson $blocks}' style="display:none;" onerror="
    (async () => {
        // 天气api
        const weather = await fetch('https://wttr.in/?format=1');
        const text = await weather.text();
  
        // 解析数据
        const result = JSON.parse(this.dataset.result);
        const first = result[0];
        const created = first.Created.replace(/^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/, '$1-$2-$3 $4:$5:$6');
  
        // 输出数据
        this.parentElement.outerHTML = `天气:${text}<br>ID:${first.ID}<br>创建时间:${created}`;
    })();
" />Loading</span>

这里添加 style="display:none",防止加载时出现默认图片。

添加 span 标签包裹,为了在加载时显示 Loading 提示。

把数据模板查询到的数据存储到 img 标签的 data-result 属性里。

然后就可以方便的用 js 处理数据了,甚至可以请求 api 等。

效果:

r103.gif

其他示例:

see https://ld246.com/article/1734062837460

<span><img src="" style="display:none;" onerror="
    (async () => {
        // 获取当前单元格
        const currCell = this.closest('div.av__cell');
        // 获取当前行
        const currRow = currCell.closest('div.av__row');
        // 获取前一个单元格的值
        let prevCellValue = 0;
        let prevCellColId = '';
        const prevCell = currCell.previousElementSibling;
        if(prevCell && prevCell.matches('div.av__cell')) {
            prevCellValue = parseFloat(prevCell.textContent);
            prevCellColId = prevCell.dataset.colId;
        }
        // 获取前一个单元格的所有前面的单元格的和
        let prevPrevCellsTotal = 0;
        const prevPrevRows = getPrevSiblings(currRow);
        prevPrevRows.forEach(prevPrevRow => {
            if(prevPrevRow) {
                const prevPrevCell = prevPrevRow.querySelector(`div.av__cell[data-col-id='${prevCellColId}']`);
                if(prevPrevCell) {
                    prevPrevCellsTotal += parseFloat(prevPrevCell.textContent);
                }
            }
        });
        // 输出数据
        this.parentElement.outerHTML = (prevCellValue + prevPrevCellsTotal).toFixed(2).replace('.00', '') || '';

        // 获取所有前面的行
        function getPrevSiblings(currRow) {
            let siblings = [];
            let sibling = currRow.previousElementSibling;
            while (sibling) {
                // 如果遇到了 div.av__row.av__row--header,则停止查找
                if (sibling.tagName.toLowerCase() === 'div' && sibling.classList.contains('av__row--header')) {
                    break;
                }
                // 收集 div.av__row 元素
                if (sibling.tagName.toLowerCase() === 'div' && sibling.classList.contains('av__row')) {
                    siblings.push(sibling);
                }
                sibling = sibling.previousElementSibling;
            }
            // 因为我们是从下往上添加的,所以最后需要反转数组来保持从上到下的顺序。
            return siblings.reverse();
        }
    })();
" />正在计算...</span>

image.png

留下你的脚步
推荐阅读