目录
getElementsByClassName()
区分树枝与树叶
高亮选中项
下一篇讲什么?
首页 web前端 js教程 基于Web标准的UI组件 — 树状菜单(2)_javascript技巧

基于Web标准的UI组件 — 树状菜单(2)_javascript技巧

May 16, 2016 pm 07:26 PM

从这篇开始,你需要拥有一些Javascript和DOM相关的知识才能顺利地学习下去。由于Javascript和DOM都不是三言两语可以说完的东西,如果你对它们还不熟悉,请先到这里学习一下再继续:Javascript在线教程(英文)、DOM在线教程(英文)。

getElementsByClassName()

  为了从一大堆HTML代码中找出我们的树状菜单(也许有多个),我们先来实现一个通过className找DOM节点的方法:getElementsByClassName。这是对浏览器自有DOM方法的一个简单但实用的扩充。

  此方法有两个参数:ele指出以哪个DOM节点为根节点寻找(也就是说只找ele的子节点),className指出符合条件的节点的class属性中必须包含怎样的className。它的返回值是一个数组,存放了所有符合条件的节点。

<code>function getElementsByClassName(ele,className) {
 //获取所有子节点
 if(document.all){
  var children = ele.all;
 }else{
  var children = ele.getElementsByTagName('*');
 }
 //遍历子节点并检查className属性
 var elements = new Array();
 for (var i = 0; i </code>
登录后复制

  最前面的一个if-else语是为了兼容IE5(IE5不能运行document.getElementsByTagName('*'))。需要注意的是千万不要用浏览器检测的方法来写脚本,而应该直接使用将要用到的语句来测试是否可以执行,如果返回值为nullundefined,那再换一种方法。这样的脚本可以有更好的兼容性,也更健壮。

  elements[elements.length] = child;,这句同样是为了兼容IE5才没有使用数组的push方法。如果你一定要使用push方法,那么可以在执行getElementsByClassName()之前先重载一遍push方法。代码如下:

<code>Array.prototype.push = function(value){
 this[this.length] = value;
}</code>
登录后复制

  注:原本我希望getElementsByClassName也能像push方法一样写,比如HTMLElement.prototype.getElementsByClassName = ...。不过实际操作的时候发现在运行时HTMLElement这个对象并不是固定的,每种tag似乎都不一样,只能作罢。如果你有解决方案请告诉我,谢谢。

  现在我们就可以方便地找出页面上所有的树状菜单了:

<code>var trees	= getElementsByClassName(document,'TreeView');
for(var i=0;i<trees.length alert i></trees.length></code>
登录后复制

  最后把上面这几句加到window.onload事件中运行,以便文档一加载完就对树状菜单进行初始化。完整的代码请查看下面例子的源代码。

  查看效果(例1)

区分树枝与树叶

  在上一篇中我们说到树枝和树叶的区别就是这个节点有没有子节点,所以判断树枝和树叶的方法也可以从这个角度来考虑。一个比较直观的方法就是遍历整个树状菜单的DOM树(注意这里两个“树”的区别),看看每个节点是不是拥有子节点,如果有的话我们就给这个节点一个专门的class以示区分。我们这里用一种比较取巧的方法,就是判断各个节点的innerHTML中有没有出现字符串'<ul>'</ul>。如果有的话,那么很显然它拥有一个或多个子节点。

<code>var trees	= getElementsByClassName(document,'TreeView');
for(var i=0;i<trees.length var nodes="trees[i].getElementsByTagName('LI');" for j="0;j<nodes.length;j++){" if>') > -1)
   nodes[j].className += 'Open';
 }
}
</trees.length></code>
登录后复制

  这里给每个树枝加了一个className:Open,因为我们现在还不能打开关闭树枝,所以只要是树枝那就是open的。当然后面我们会用到Close的:)。相应的修改一下CSS,给树枝一个带减号的图标,表示它是打开的:

<code>.TreeView li.Open{
 background:transparent url(opened.gif) 12px 2px no-repeat;
}</code>
登录后复制

  查看效果(例2)

高亮选中项

  接下来实现把当前选中的树枝(或树叶)高亮的功能。有两个时候需要高亮:菜单初始化的时候和点击某个菜单项的时候。

  初始化的时候比较容易处理,直接给需要高亮的节点一个特殊的Class即可,比如“Selected”:

<code>.TreeView li.Selected a:link,
.TreeView li.Selected a:visited,
.TreeView li.Selected a:hover,
.TreeView li.Selected a:active{
 background-color:#05F;
 color:#FFF;
 text-decoration:none;/*去除下划线*/
 cursor:default;/*让光标变为普通箭头,假装是不能点的^_^*/
 padding:0 2px;/*为了美观考虑,也可以不要这句*/
}</code>
登录后复制

  查看效果(例3)

  这里有几点可能还需要补充说明一下:

  1. 选择器(Selector)的前面为什么要加上.TreeView,这不是冗余代码吗?
    在这个例子中确实是冗余代码,但在实际项目中,一个页面上可能会有各种不同的组件,比如还有一个菜单,被选中的菜单项也用.Selected来表示。这时就需要在选择符的前面先指出是什么组件的选中项以防冲突。当然还有其他的解决办法,比如这里的类不取名为Selectd,改为TreeSelected或者其他什么的,但是这样做人为的把命名方案复杂化了,我个人不推荐这样做。
  2. 选择器为什么分作四行来写?
    因为我们之前已经设置过a的样式,为了提高优先级重载旧的样式,所以需要指定a的四种伪状态(还有其他提高优先级的办法,关于优先级算法,在《网站重构》一书中有详细说明)。
  3. Selected为什么要用在li上,而不直接用在a上?
    这又是一个不太容易说明白的地方,因为很大程度上它是一种个人习惯,只是我个人觉得这样做更合适一些。事实上,写在li上或a上都是可以的,至少看上去(表现层的视角)不会有太大的区别,但是如果你从“表现层”中跳出来,站在“结构层”的视角来看,无论这个菜单的树结构还是DOM结构,一个节点都是由一个li来表达的,a只不过是这个节点内的更细节的部分。虽然我最终是希望给a指定一个特殊的样式(为什么不指定给li?你可以自己试一下),但从XHTML结构来说,这个class="Selected"还是写在li上更合适。(上帝保佑我说清楚了……)

下一篇讲什么?

  这篇文章是我第一次加入Javascript内容,不是很清楚是说浅了还是说深了,请大家在右边留言告诉我你的想法。从下一篇开始,我们开始进入部署鼠标事件和响应鼠标事件方面的内容。也许从下下篇开始再加入一些Javascript面向对象编程的内容,待定待定……hehe^_^

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
<🎜>掩盖:探险33-如何获得完美的色度催化剂
2 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1677
14
CakePHP 教程
1430
52
Laravel 教程
1333
25
PHP教程
1278
29
C# 教程
1257
24
Python vs. JavaScript:学习曲线和易用性 Python vs. JavaScript:学习曲线和易用性 Apr 16, 2025 am 12:12 AM

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

JavaScript和Web:核心功能和用例 JavaScript和Web:核心功能和用例 Apr 18, 2025 am 12:19 AM

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

JavaScript在行动中:现实世界中的示例和项目 JavaScript在行动中:现实世界中的示例和项目 Apr 19, 2025 am 12:13 AM

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

了解JavaScript引擎:实施详细信息 了解JavaScript引擎:实施详细信息 Apr 17, 2025 am 12:05 AM

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python vs. JavaScript:开发环境和工具 Python vs. JavaScript:开发环境和工具 Apr 26, 2025 am 12:09 AM

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

C/C在JavaScript口译员和编译器中的作用 C/C在JavaScript口译员和编译器中的作用 Apr 20, 2025 am 12:01 AM

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。 1)C 用于解析JavaScript源码并生成抽象语法树。 2)C 负责生成和执行字节码。 3)C 实现JIT编译器,在运行时优化和编译热点代码,显着提高JavaScript的执行效率。

Python vs. JavaScript:比较用例和应用程序 Python vs. JavaScript:比较用例和应用程序 Apr 21, 2025 am 12:01 AM

Python更适合数据科学和自动化,JavaScript更适合前端和全栈开发。1.Python在数据科学和机器学习中表现出色,使用NumPy、Pandas等库进行数据处理和建模。2.Python在自动化和脚本编写方面简洁高效。3.JavaScript在前端开发中不可或缺,用于构建动态网页和单页面应用。4.JavaScript通过Node.js在后端开发中发挥作用,支持全栈开发。

从网站到应用程序:JavaScript的不同应用 从网站到应用程序:JavaScript的不同应用 Apr 22, 2025 am 12:02 AM

JavaScript在网站、移动应用、桌面应用和服务器端编程中均有广泛应用。1)在网站开发中,JavaScript与HTML、CSS一起操作DOM,实现动态效果,并支持如jQuery、React等框架。2)通过ReactNative和Ionic,JavaScript用于开发跨平台移动应用。3)Electron框架使JavaScript能构建桌面应用。4)Node.js让JavaScript在服务器端运行,支持高并发请求。

See all articles