繁体   English   中英

反应动态tabindex创建

[英]React dynamic tabindex creation

我正在寻找一种方法来动态创建我的React应用程序中每个元素的tabindex 有多个组件包含我想要创建tabindex输入元素,我不知道如何协调它们并避免碰撞。

我的React应用程序由包含输入元素的多个表组成。 在运行时,用户可以通过创建其他输入元素来扩展表。 我想改变用户通过这些输入进行选项卡的方向,但我不确定如何为每个元素生成tabindex

到目前为止我想出的方式:

  • 每个表有一个固定的偏移量(但我不知道单个表中可能有多少输入, tabindex应该保持在32767以下,所以我不能假设巨大的差距)
  • tabindex偏移传递给表并从React对象获取使用的tabindex数量以计算下一个偏移量(在我看来它会破坏模块性并且难以实现)
  • 通过全局状态跟踪下一个tabindex (hacky并且可能在表扩展时中断)
  • 通过dom树跟踪下一个tabindex (不知道如何实现)

我缺少tabindex创建的工具或通用实践吗?

我不知道你是否已经弄清楚了这一点。 但是你可以在这里使用一些技巧。

您不需要为表中的每个单元格使用不同的tabindex来进行所需的选项卡导航。 您只需要为表中的每列提供不同的tabindex 您可以为同一列中的每个单元重复相同的tabindex 因为当tabindex相同时,浏览器只使用HTML元素顺序来决定下一个控件,这就是我们在这种情况下所需要的。 因此,表格的tabindex分配将是这样的。

1   2   3   4
1   2   3   4
1   2   3   4
1   2   3   4

这是一个重大的胜利。 因为对于10X10表,我们不需要100个不同的选项卡索引。 我们只需10个索引即可完成。

这是一个用React演示这个想法的小例子。 你可以运行它看看。

 // Table class Table extends React.Component { generateRows(){ const offset = this.props.tabIndexOffSet; const cols = this.props.cols; const data = this.props.data; return data.map(function(item) { const cells = cols.map(function(colData, index) { return ( <td key={colData.key}> <input type="text" value={item[colData.key]} tabIndex={offset+index} /> </td> ); }); return (<tr key={item.id}> {cells} </tr>); }); } generateHeaders() { var cols = this.props.cols; return ( <tr> { cols.map(function(colData) { return <th key={colData.key}> {colData.label} </th>; }) } </tr> ); } render(){ const headerComponents = this.generateHeaders(); const rowComponents = this.generateRows();; return ( <table> <thead> {headerComponents} </thead> <tbody> {rowComponents} </tbody> </table> ); } } // App class App extends React.Component{ constructor(){ super(); this.state = { cols: [ { key: 'firstName', label: 'First Name' }, { key: 'lastName', label: 'Last Name' } ], data: [ { id: 1, firstName: 'John', lastName: 'Doe' }, { id: 2, firstName: 'Clark', lastName: 'Kent' }, { id: 3, firstName: 'Tim', lastName: 'Walker' }, { id: 4, firstName: 'James', lastName: 'Bond' } ] } } render () { return ( <div> <Table tabIndexOffSet={1} cols={this.state.cols} data={this.state.data}/> <Table tabIndexOffSet={3} cols={this.state.cols} data={this.state.data}/> </div> ); } } // Render ReactDOM.render( <App/>, document.getElementById('container') ); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="container"></div> 

如果使用这种方法可以管理列数,我建议您使用第一个选项,为每个表分配不同的偏移量(也在上面的例子中说明)。如果列数是固定的,那么它将很容易。 即使不是,您也可以尝试根据您的用例与固定的硬编码偏移保持一些合理的差距。

如果这不起作用,那么您可以做的下一件事就是尝试从数据中计算偏移值。 我假设您将拥有由此表表示的某种数据,如对象数组或数组数组,可能处于您的应用程序状态。 因此,您可以根据这些数据导出表的偏移量。 如果您正在使用像Redux这样的状态管理库,那么它将非常简单,我建议您查看可用于在Redux中计算派生状态的重新选择

希望这可以帮助!

对于常见的从左到右的DOM相关表示,它可以是:

var el = document.documentElement,
    rebuildIndex = function () {
        document.getElementsByTagName('input').forEach(function (input, idx) {
            input.setAttribute('tabindex', idx);
        });
    };
// Firefox, Chrome
if (support.DOMSubtreeModified) {
    el.addEventListener('DOMSubtreeModified', rebuildIndex, false);
// Safari, Opera
} else {
    el.addEventListener('DOMNodeInserted', rebuildIndex, false);
    el.addEventListener('DOMNodeRemoved', rebuildIndex, false);
}

这是一个可以在每次将新输入添加到布局时调用的函数。 它为每个输入分配tabIndex ,没有任何间隙,并且容纳各种大小的表,其中每个单元可以具有任意数量的输入元素。 你可以在这个jsfiddle中测试它。

输入元素存储在Map对象中,其中每个键是表,列和行索引的组合。 然后对键进行排序,并按排序键的顺序设置tabIndex属性。

function setTabIndices() {
    var tableIndex, rowIndex, colIndex, inputIndex;
    var table, row, cell, inputs;
    var map = new Map();
    var tables = document.getElementsByTagName("table");
    for (tableIndex = 0; tableIndex < tables.length; tableIndex++) {
        table = tables[tableIndex];
        for (rowIndex = 0; rowIndex < table.rows.length; rowIndex++) {
            row = table.rows[rowIndex];
            for (colIndex = 0; colIndex < row.cells.length; colIndex++) {
                cell = row.cells[colIndex];
                inputs = cell.getElementsByTagName("input");
                for (inputIndex = 0; inputIndex < inputs.length; inputIndex++) {
                    // Define key based on table, column, and row indices
                    map.set(format(tableIndex, 4) + format(colIndex, 6) +
                             format(rowIndex, 6) + format(inputIndex, 3), 
                             inputs[inputIndex]);
                }
            }
        }
    }
    var input;
    var sortedKeys = [...map.keys()].sort(); // Not supported in IE11
    for (var tabIndex = 1; tabIndex <= sortedKeys.length; tabIndex++) {
        input = map.get(sortedKeys[tabIndex - 1]);
        input.tabIndex = tabIndex;
    }
}

function format(value, digits) {
    return ("0000000000" + value.toString()).slice(-digits);
}


注意:以下行导致IE中出现问题,它不支持扩展语法

 var sortedKeys = [...map.keys()].sort(); 

如果必须支持IE,则可以调用map.forEach来填充未排序的数组, 如此修改后的jsfiddle所示。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM