목차
getElementsByClassName()
区分树枝与树叶
高亮选中项
웹 프론트엔드 JS 튜토리얼 웹 표준 기반의 UI 컴포넌트 - 트리 메뉴(2)_javascript 기술

웹 표준 기반의 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 &lt; children.length; i++) {
  var child = children[i];
  var classNames = child.className.split(' ');
  for (var j = 0; j &lt; classNames.length; j++) {
   if (classNames[j] == className) {
    elements[elements.length] = child;
    break;
   }
  }
 }
 return elements;
}</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&lt;trees.length;i++){
 alert('我是第' + i + '个树状菜单');
 //在这里可以更细致地处理每一个树状菜单
}</CODE>
로그인 후 복사

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

  查看效果(例1)

区分树枝与树叶

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

<code>var trees	= getElementsByClassName(document,'TreeView');
for(var i=0;i&lt;trees.length;i++){
 //先把所有的节点找出来
 var nodes = trees[i].getElementsByTagName('LI');
 //判断各个节点是否有子节点
 for(var j=0;j&lt;nodes.length;j++){
  if(nodes[j].innerHTML.toLowerCase().indexOf('&lt;ul&gt;') &gt; -1)
   nodes[j].className += 'Open';
 }
}
</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. 를 추가해야 하는 이유는 중복된 코드가 아닌가요? 이 예제에서는 .TreeView가 정말 중복된 코드이지만, 실제 프로젝트에서는 페이지에 메뉴 등 다양한 구성요소가 있을 수 있으며, 선택한 메뉴 항목도
    로 표시됩니다. 이때 선택기 앞에 어떤 컴포넌트가 선택되어 있는지 표시해 주어야 충돌을 방지할 수 있습니다. 물론 여기에서 클래스 이름을 Selectd로 지정하지 않고 TreeSelected 등으로 변경하는 등의 다른 해결 방법도 있지만 이는 명명 체계를 인위적으로 복잡하게 만들어 개인적으로 권장하지 않습니다. .Selected선택자는 왜 4줄로 작성되나요?
  2. 이전에
    의 스타일을 설정했기 때문에 이전 스타일을 오버로드하여 우선순위를 높이려면 a의 4가지 의사 상태를 지정해야 합니다(우선순위를 높이는 다른 방법도 있습니다. 우선순위 알고리즘, "a웹사이트 재구성" 책에 자세히 설명되어 있습니다. 에 직접 사용하는 대신
  3. Selectedli을 사용해야 하는 이유는 무엇인가요? a대부분 개인적인 습관이라 설명하기 쉽지 않은 또 다른 곳이지만 개인적으로는 이 곳이 더 적절하다고 생각합니다. 사실
    이나 li에 써도 괜찮지만, 적어도 (프리젠테이션 레이어 입장에서는) 크게 다르지는 않겠지만, '프리젠테이션 레이어'에서 뛰어내려 올라서면 "구조적 레이어"의 관점에서는 이 메뉴의 트리 구조나 DOM 구조에 관계없이 노드는 a로 표현되며 li는 이 노드의 좀 더 상세한 부분일 뿐입니다. 궁극적으로 a에 특별한 스타일을 할당하고 싶지만(a에 할당하면 어떨까요? 직접 시도해 볼 수 있습니다) XHTML 구조 측면에서 liclass="Selected"를 작성하는 것이 더 적절합니다. . (분명히 말씀드렸지만...) li
다음에는 무슨 이야기를 할까요?

이번 글은 자바스크립트 내용을 처음 추가한 글이라 얕은지 깊은지 알 수 없습니다. 오른쪽에 의견을 남겨주세요. 다음 글부터 마우스 이벤트를 배포하고 마우스 이벤트에 응답하는 내용을 살펴보겠습니다. 어쩌면 다음 글에 Javascript 객체 지향 프로그래밍 콘텐츠를 추가할지 결정될지도 모르겠습니다... 헤헤^_^

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

뜨거운 기사 태그

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

JavaScript로 문자열 문자를 교체하십시오 JavaScript로 문자열 문자를 교체하십시오 Mar 11, 2025 am 12:07 AM

JavaScript로 문자열 문자를 교체하십시오

사용자 정의 Google 검색 API 설정 자습서 사용자 정의 Google 검색 API 설정 자습서 Mar 04, 2025 am 01:06 AM

사용자 정의 Google 검색 API 설정 자습서

예제 색상 JSON 파일 예제 색상 JSON 파일 Mar 03, 2025 am 12:35 AM

예제 색상 JSON 파일

8 멋진 jQuery 페이지 레이아웃 플러그인 8 멋진 jQuery 페이지 레이아웃 플러그인 Mar 06, 2025 am 12:48 AM

8 멋진 jQuery 페이지 레이아웃 플러그인

10 JQuery Syntax Highlighter 10 JQuery Syntax Highlighter Mar 02, 2025 am 12:32 AM

10 JQuery Syntax Highlighter

자신의 Ajax 웹 응용 프로그램을 구축하십시오 자신의 Ajax 웹 응용 프로그램을 구축하십시오 Mar 09, 2025 am 12:11 AM

자신의 Ajax 웹 응용 프로그램을 구축하십시오

' this ' 자바 스크립트로? ' this ' 자바 스크립트로? Mar 04, 2025 am 01:15 AM

' this ' 자바 스크립트로?

10 JavaScript & JQuery MVC 자습서 10 JavaScript & JQuery MVC 자습서 Mar 02, 2025 am 01:16 AM

10 JavaScript & JQuery MVC 자습서

See all articles