react获取ref react获取元素位置
论文深入探讨如何在JavaScript/React环境中,根据我们的阵列元素的id和reference_id字段,实现对阵列的复杂重排序。将介绍构建自定义键来将子元素整理到其父元素之后,从而实现排序的节点结构展示,并提供示例代码和注意事项,帮助开发者解决此类数据组织难题。理解阵列重排序问题
在阵列开发中,我们经经常会遇到根据特定逻辑对数据队列进行重排的需求。一个常见的场景是处理具有父子关系的数据结构,每个元素可能包含一个id和一个紧的reference_id(或parent_id),reference_id考虑指向其父元素的id。我们的目标是所有子元素都跟在它们的父元素之后,其中即使父元素本身没有reference_id(即是顶级元素)。
以下数据结构:const initialArray = [ { id: 1, name: 'hello world', reference_id: null }, { id: 2, name: 'hello world', reference_id: null }, { id: 3, name: 'hello world',reference_id: 1 }, { id: 4, name: 'hello world',reference_id: null }, { id: 5, name: 'hello world',reference_id: 1 }, { id: 6, name: 'hello world',reference_id: 2 },];登录后复制
我们期望的排名结果是:[ { id: 1, name: 'hello world',reference_id: null }, { id: 3, name: 'hello world',reference_id: 1 }, { id: 5, name: 'hello world',reference_id: 1 }, { id: 2, name: 'hello world',reference_id: null }, { id: 6, name: 'hello world',reference_id: 2 }, { id: 4, name: '你好world',reference_id: null },]登录后复制
可以看到,id:3和id:5(它们的reference_id都是1)被排在了id:1之后;id:6(reference_id是2)被排在了id:2。
之后直接使用findIndex和splice等方法来动态存储通常会导致复杂且难以维护的代码,尤其是在循环中修改存储阵列和索引时,很容易产生“意外结果”或逻辑错误。更推荐的做法是利用存储的排序方法,结合自定义的比较函数。
立即学习《Java免费学习笔记(深入)》;解决方案一:两步映射与排序
这种方法的核心思想是:首先为每个元素创建一个临时的排序键,然后根据这个键进行排序,最后去掉这个临时键,还原为原始对象。
实现步骤再次创建原始数组,为每个原始元素生成一个包含数据和排序键的新对象。排序键通常由reference_id和id组合而成。执行排序:根据Array.prototype.sort()方法,新对象中的排序键进行比较。数据:遍历排序后的数组,取出出数据原始对象。示例代码const arr = [ { id: 1, name: 'hello world', reference_id: null }, { id: 2, name: 'hello world',reference_id: null }, { id: 3, name: 'hello world',reference_id: 1 }, { id: 4, name: 'hello world',reference_id: null }, { id: 5, name: 'hello world',reference_id: 1 }, { id: 6, name: 'hello world',reference_id: 2 },];const SortedResult = arr .map(item =gt; ({ // 构建排序键:将reference_id视为父ID,如果为null则视为空字符串, // 然后拼接当前id。这样,父元素(reference_id为null)的键会完善id开头, // 子元素(reference_id为父id)的键会父id开头。 // 例如: // id: 1, ref: null -gt; quot;1quot; // id: 3, ref: 1 -gt; quot;13quot; // id: 5, ref: 1 -gt; quot;15quot; // id: 2, ref: null -gt; quot;2quot; // id: 6, ref: 2 -gt; quot;26quot; sortKey: `${item.reference_id ?? ''}${item.id}`,originalElement: item, })) .sort((a, b) =gt; a.sortKey.localeCompare(b.sortKey)) // 使用 localeCompare 进行字符串比较 .map(item =gt; item.originalElement); // 还原原始对象 console.log(sortedResult);登录后复制关键点解析item.reference_id ?? '':使用空字符串来代替 null 的引用_id,确保拼接时不会出现 null1 这样的字符串。localeCompare(b.sortKey):这是一个字符串比较方法,因为它会根据当前比较语言环境的排序规则进行,对于数字字符串也能很好地处理。优点:逻辑清晰,分步执行,容易理解。缺点:增加了额外的内存开销,需要创建中间对象仓库。对于非常大的数据集,这可能成为一个考虑因素。
解决方案二:单次排序与自定义比较函数
为了避免创建中间对象,我们可以直接在排序方法的比较函数中动态生成排序键。这种方法更高效,但函数比较定义的逻辑可能略显复杂。实现步骤排序键生成函数:一个辅助函数,它接收一个元素,并返回一个用于比较的字符串。执行排序:直接使用Array.prototype.sort()方法,并在比较函数中调用上述辅助函数来获取排序键。示例代码const arr = [ { id: 1, name: 'hello world',reference_id: null }, { id: 2, name: 'hello world',reference_id: null }, { id: 3, name: 'hello world',reference_id: 1 }, { id: 4, name: 'hello world',reference_id: null }, { id: 5, name: 'hello world', reference_id: 1 }, { id: 6, name: 'hello world', reference_id: 2 },];//定义一个函数来生成元素的排序标准字符串 const getSortCriterion = (item) =gt; { // 1.处理reference_id:如果为null,则视为空字符串。 // 2.使用padStart(4, quot;0quot;)确定数字字符串长度一致,防止quot;10quot;lt;quot;2quot;的错误比较。 // 如:id=1 -gt; quot;0001quot;, id=10 -gt; quot;0010quot; // 3.使用quot;|quot;作为分隔符,确保reference_id和id的组合不会混淆。 //如:ref=1, id=2 -gt; quot;0001|0002quot; // ref=12, id=3 -gt; quot;0012|0003quot; const refIdString = (quot;quot;(item.reference_id ?? quot;quot;)).padStart(4, quot;0quot;); const idString = (quot;quot; item.id).padStart(4, quot;0quot;); return `${refIdString}|${idString}`;};//对队列进行排序 const SortedResult = [...arr].sort((a, b) =gt; getSortCriterion(a).localeCompare(getSortCriterion(b)));console.log(sortedResult);console.log(quot;计算出的排序标准(用于调试):quot;);console.log(sortedResult.map(getSortCriterion));登录后关键点解析 getSortCriterion(item) 函数:是核心。
项目.reference_id ?? "":同上,处理空值。.padStart(4, "0"):解决数字排序排序问题的关键。如果不进行填充,"10"会在localeCompare中被认为小于"2"(因为它们都是字符串,按字符逐个比较)。通过padStart,1变为"0001",10变为"0010",2变为"0002",这样"0001" lt; "0002" lt; "0010" 可以正确比较。这里的 4 假设 id 不会超过四位数(9999)。如果 id 可能更大,需要调整填充长度。"|" 分隔符:确保reference_id 和 id 的组合不会产生歧义。例如,如果reference_id 是1,id 是23,组合是123;如果reference_id 是12,id 是3,组合也是123。使用分隔符可以避免这种情况。[...arr].sort(...): sort()方法会修改原阵列。为了保持阵列的不可变性(在React等框架中非常重要),我们通常会先创建一个浅拷贝[...arr],然后再进行排序。优点是:避免了创建中间阵列,内存效率更高。比较函数处理更复杂的数字ID。缺点:比较函数内部逻辑相对复杂,需要padStart的作用。注意事项与最佳实践不可变性:Array.prototype.sort()方法会直接修改原阵列。在React中或者其他需要保持数据不可变的场景中,一定要先创建磁盘的浅拷贝,例如[...originalArray].sort(...),一行。ID类型:确保id和reference_id 的数据类型一致,通常是数字或字符串。如果是混合类型,可能需要在比较函数中进行类型转换。padStart 的长度:在解决方案二中,padStart(4, "0") 假设 id 最大为四位数。如果 id 可能更大(例如五位数或更多),则需要相应地增加填充长度(例如 padStart(5, "0"))。性能考量:对于非常大的数据库,排序方法的性能是 O(N log N)。在比较函数中执行复杂的字符串操作(如padStart和字符串拼接)会增加每次比较的开销。对于大多数前置应用来说,这通常不是问题,但如果遇到性能瓶颈,可能需要考虑其他数据结构进一步优化的算法。多系统排序:这两种方法都适用于简单的父子体系。如果需要处理多层格式化的体系结构(例如祖父-父子),可能需要更复杂的排序树排序逻辑或将数据转换为形结构进行涂层处理。总结
通过构建的排序自定义键,我们可以根据id和reference_id来解决有效的问题 对阵列进行复杂重排序的问题。无论是采用两步映射和排序的时序方法,还是单次排序与自定义比较函数的更能够高效的方法,关键都在于设计一个准确反映期望顺序的比较逻辑。在实际开发中,根据项目需求和数据规模选择最合合适的方案,并始终注意保持代码的不可变性和可维护性。
以上就是JavaScript/React中根据ID和引用ID实现复杂集群重排序教程的详细内容,更多请关注乐哥常识网其他相关文章!