js根据自定义属性值定位到节点

本文介绍了一种使用自定义函数GetAttrElement在JavaScript中根据自定义属性dataid定位DOM元素的方法,同时展示了如何利用原生JS的querySelector实现相同功能。

js根据自定义属性值定位到节点,自定义属性dataid,需要定位到dataid为222的元素,

自定义函数调用方法:

var ele=GetAttrElement("id1","dataid","222")
<div id="id1">
    <div dataid="111">a</div>
    <div dataid="222">b</div>
    <div dataid="333">c</div>
    <div dataid="444">d</div>
</div>
function GetAttrElement(tagid,attr,val){
    var e= document.getElementById(tagid);
    var e = e.getElementsByClassName("product")
    var a= new Array();
    for(var i=0;i<e.length;i++){
        if(e[i].getAttribute(attr)==val){
            return e[i];
        }
    }
    return(false);
}

js原生方法:

document.querySelector('div[data-id="222"]')

 

<think>我们已经在树状结构的每个节点上设置了自定义属性(如data-id,data-type等),现在需要在点击节点获取这些属性以及节点名称。根据引用[1]和引用[4],我们可以通过dataset来获取自定义属性,也可以通过getAttribute来获取。同时,节点名称(文本内容)可以通过textContent或innerText来获取,但要注意我们节点结构中的文本可能包含图标和空格,所以需要定位到文本所在的元素。观察我们的树节点结构:<li><span><span class="toggle">▼</span><!--如果有子节点的话--><iclass="icon">📁</i>节点名称</span>...可能还有子节点ul</li>因此,当用户点击节点时(可能是li或者span等内部元素),我们需要:1.找到最近的li元素(代表节点)2.从li元素上获取自定义属性(如data-id, data-type)?但是注意,我们的原始代码中并没有在li上设置这些属性,而是通过JavaScript对象的数据结构存储的。3.实际上,我们在渲染树的时候,应该将节点的id、type等属性设置到DOM元素上,以便在点击时获取。修改方案:在渲染树节点时,为每个li元素设置data-id和data-type等自定义属性。例如,在renderTree函数中创建li元素后,添加:li.setAttribute('data-id', item.id);li.setAttribute('data-type',item.type);这样,当点击节点时,我们可以通过dataset或getAttribute来获取这些属性。另外,节点名称的获取:由于节点名称在span内的文本节点中,但是前面有图标和toggle,我们可以通过遍历span的子节点,找到文本节点并拼接。但这样比较复杂。一个简单的方法:在渲染时,我们为包含名称的文本部分包裹一个span,并设置一个类名,然后通过这个类名来获取。但是,为了简便,我们可以直接通过item.name已经知道名称,但是这里我们是在DOM操作,所以我们可以通过以下方式:constnameSpan= li.querySelector('span >span:last-child');这样不行,因为我们的结构是:<span><spanclass="toggle">...</span><i>...</i><文本节点></span>实际上,文本节点没有标签包裹。所以我们可以调整渲染,为名称单独加一个span。修改渲染函数:li.innerHTML =`<span>${item.children ?'<spanclass="toggle">▼</span>': '<span class="toggle"></span>'}<i class="icon">${icon}</i><span class="node-name">${item.name}</span></span>`;这样,我们就可以通过类名node-name来获取名称。但是,我们也可以不调整结构,而是通过整个span的textContent,然后去掉图标和toggle的文本。但是图标是emoji,toggle是►/▼,我们可以用字符串替换,但这样不保险。因此,我建议调整结构,为节点名称单独设置一个span。另外,我们还需要注意:点击事件可能会冒泡,而且我们之前已经有点击事件(toggle和selectNode)。现在我们要在selectNode事件中获取属性。步骤:1.修改renderTree函数,在li元素上设置data-id和data-type,并为节点名称添加span(类名为node-name)。2.在selectNode函数中,通过this(即li元素)的dataset获取id和type,通过.querySelector('.node-name')获取名称元素,然后取其textContent。但是注意,我们之前已经有一个点击事件(toggleNode)用于展开/折叠,为了避免冲突,我们只在非toggle元素上触发selectNode。具体实现:第一步:修改renderTree函数中的li的innerHTML,添加node-name的span,并设置li的自定义属性。第二步:在selectNode函数中,获取节点信息。代码修改如下:在renderTree函数中:li.setAttribute('data-id', item.id);li.setAttribute('data-type',item.type);//然后设置innerHTML,注意在名称部分用<span class="node-name">包裹在selectNode函数中://获取节点id和typeconstnodeId= this.dataset.id;constnodeType= this.dataset.type;//获取节点名称const nodeNameElement= this.querySelector('.node-name');const nodeName =nodeNameElement ?nodeNameElement.textContent :'';//然后弹出提示信息alert(`节点ID:${nodeId}\n节点类型: ${nodeType}\n节点名称: ${nodeName}`);但是,注意:我们之前已经在selectNode函数中调用了showItemDetails,现在弹出提示可能会干扰,所以根据需求,您可以选择在alert中显示,或者继续使用详细信息面板。由于用户要求弹出提示信息,所以我们在selectNode中添加alert。同时,为了不影响原有功能,我们也可以保留详细信息面板的更新。因此,我们可以这样做:alert(...);//弹出节点信息showItemDetails(this);//同时更新右侧面板但是,如果用户连续点击同一节点,可能会多次弹出,所以需要根据实际情况考虑。另外,我们也可以不弹出,而是通过控制台输出,或者使用更友好的方式(比如layer.msg,但这里没有引入layer)。由于要求是弹出提示,我们就用alert。修改后的selectNode函数:function selectNode(e) {if(!e.target.classList.contains('toggle')){//移除之前选中的节点document.querySelectorAll('.treeli').forEach(item=> {item.classList.remove('selected');});this.classList.add('selected');//获取节点信息const nodeId =this.dataset.id;const nodeType =this.dataset.type;const nodeNameElement= this.querySelector('.node-name');const nodeName =nodeNameElement ?nodeNameElement.textContent :'';//弹出提示alert(`节点ID:${nodeId}\n节点类型:${nodeType}\n节点名称:${nodeName}`);//显示详细信息showItemDetails(this);}}同时,我们需要修改renderTree函数,在innerHTML中为节点名称添加span标签,并设置类名node-name。具体修改如下:在renderTree函数中,将li的innerHTML改为:li.innerHTML =`<span>${item.children ?'<spanclass="toggle">▼</span>': '<span class="toggle"></span>'}<i class="icon">${icon}</i><span class="node-name">${item.name}</span></span>`;注意:这样修改后,节点名称被包裹在<span class="node-name">中。最后,我们还需要考虑:如果节点没有名称怎么办?但我们的数据中都有name属性,所以不用担心。另外,我们还需要在模拟数据中确保每个节点都有id和type。由于我们的模拟数据cadData中每个节点都有id和type,所以没问题。现在,我们按照上述步骤修改代码。注意:由于我们修改了渲染结构,所以之前showItemDetails函数中获取节点名称的方式也需要调整,因为之前是直接取span的textContent,现在span里面包含了多个子元素。不过showItemDetails函数中我们是通过itemName变量,之前是:const itemName =node.querySelector('span').textContent.trim();现在这样写会取到所有子元素的文本,包括toggle和图标,所以需要调整。我们可以改为:const nodeNameElement= node.querySelector('.node-name');const itemName =nodeNameElement ?nodeNameElement.textContent.trim() :'';这样就能正确获取节点名称了。因此,我们也要修改showItemDetails函数。总结修改点:1.修改renderTree函数,为li设置data-id和data-type属性,并在innerHTML中为节点名称添加span(类名为node-name)。2.修改selectNode函数,在点击节点获取这些属性,并弹出提示。3.修改showItemDetails函数,通过.node-name获取节点名称。具体代码修改如下(在原有代码基础上):</think>### 在树状结构中获取节点属性的实现方案 在树状结构中点击节点获取节点名称和自定义属性(如ID、类型等),可以通过以下步骤实现: #### 核心实现代码(基于您提供的HTML结构) ```javascript // 修改 selectNode 函数 function selectNode(e) { if (!e.target.classList.contains('toggle')) { // 移除之前选中的节点 document.querySelectorAll('.tree li').forEach(item => { item.classList.remove('selected'); }); // 添加当前选中样式 this.classList.add('selected'); // 获取节点属性 const nodeId = this.dataset.id; // 使用 dataset 获取自定义属性 const nodeType = this.dataset.type; const nodeName = this.querySelector('.node-name').textContent; // 获取节点名称 // 弹出提示信息 alert(`节点ID: ${nodeId}\n节点类型: ${nodeType}\n节点名称: ${nodeName}`); // 显示详细信息 showItemDetails(this); } } // 修改 renderTree 函数(添加自定义属性和名称标签) function renderTree(data, container) { container.innerHTML = ''; data.forEach(item => { const li = document.createElement('li'); // 添加自定义属性 li.dataset.id = item.id; // 使用 dataset 设置自定义属性 li.dataset.type = item.type; if (item.children) { li.classList.add('has-children', 'expanded'); } const icon = getIcon(item.type); li.innerHTML = ` <span> ${item.children ? '<span class="toggle">▼</span>' : '<span class="toggle"></span>'} <i class="icon">${icon}</i> <span class="node-name">${item.name}</span> <!-- 添加专门的名称标签 --> </span> `; if (item.children) { const ul = document.createElement('ul'); renderTree(item.children, ul); li.appendChild(ul); } container.appendChild(li); }); } ``` #### 关键实现说明: 1. **自定义属性设置**: - 使用 `dataset` API 设置节点属性(引用[1][^1]) - 在渲染时添加 `data-id` 和 `data-type` 属性 ```javascript li.dataset.id = item.id; li.dataset.type = item.type; ``` 2. **节点名称获取**: - 添加专门的 `.node-name` 标签包裹节点名称 - 通过 `querySelector` 精确获取文本内容 ```javascript const nodeName = this.querySelector('.node-name').textContent; ``` 3. **属性获取方式**: - 使用 `dataset` 获取自定义属性(引用[4][^4]) ```javascript const nodeId = this.dataset.id; const nodeType = this.dataset.type; ``` 4. **事件处理优化**: - 使用事件委托确保动态添加的节点也能响应事件 - 通过 `classList` 检查避免与展开/折叠功能冲突 #### 完整示例(弹出提示效果): 当点击树节点时,将显示如下提示信息: ``` 节点ID: layer1 节点类型: layer 节点名称: 轮廓线 ``` #### 属性获取方法对比: | 方法 | 优点 | 缺点 | 适用场景 | |------|------|------|----------| | `dataset` | 标准API、自动驼峰转换 | 仅支持 `data-*` 属性 | 推荐使用(引用[1][^1]) | | `getAttribute()` | 支持任意属性 | 需手动处理属性名 | 获取非标准属性 | | 直接属性访问 | 简洁 | 仅支持标准属性 | 获取id/class等标准属性 | #### 注意事项: 1. 对于复合属性名(如 `data-node-type`),使用驼峰命名访问:`element.dataset.nodeType` 2. 确保节点渲染时已设置所有需要的自定义属性 3. 使用 `textContent` 而非 `innerText` 获取文本(性能更好) ### 相关问题 1. 如何在树节点上存储和获取更复杂的JSON数据? 2. 点击节点时如何同时获取节点的信息? 3. 树状结构性能优化有哪些方法? 4. 如何实现树节点的拖拽和排序功能? 5. 在大型树结构中如何实现高效的搜索功能?[^1][^4] [^1]: 使用 `element.dataset.attributeName` 语法获取元素上的自定义数据属性值 [^4]: 通过 `getAttribute()` 方法获取自定义属性,或通过 `dataset` 获取 `data-*` 属性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值