日期:2014-05-16  浏览次数:20403 次

详解用JavaScript实现"树形菜单"效果

网页里的树形菜单有两种实现方式:一种是结合后台(JSP/Struts2等), 每次下载不同的数据来刷新页面,实现树形菜单的效果。另一种是由纯JavaScript方式来实现,在树形菜单的工作过程中,不会反复从后台重新下载页面。本文要介绍的就是用纯JavaScript来实现一个树形菜单。

1. 原理

基本原理是利用HTML Tag的innerHTML属性来实现动态效果,像<div> <span> <p>等标签都可以作为一个容器,通过控制其innerHTML来刷新显示内容。显然,其内容是由JavaScript来动态生成的。

做一个例子演示一下:

<span id="sample"></span>

<script>
	var sampleExpanded = true; 
	function sampleOnClick()
	{
		sampleExpanded = ! sampleExpanded;
		sampleRefreshUI();
	}
	
	function sampleRefreshUI()
	{
		var html = "<a href='javascript:sampleOnClick()' > ";
		if(sampleExpanded)
		{
			html += "-";
			html += " 菜单项<br/>";
			html += "</a>";
			html += "    ---子菜单1---<br/>";
			html += "    ---子菜单2---<br/>";
			html += "    ---子菜单3---<br/>";
		}
		else
		{
			html += "+";
			html += " 菜单项<br/>";
			html += "</a>";
		}	
		
		document.getElementById("sample").innerHTML = html;		
	}
	
	sampleRefreshUI();
</script>

其中,

(1) 要放一个内容为空的<span>作为目标容器,我们用JavaScript动态修改其中的HTML内容

(2) 定义一个变量sampleExpanded 来存储状态: true, 当前为展开, false当前为折叠

(3) 在容器里放上链接 <a href="javascript:sampleOnClick( )">  *** </a>,当该链接被点击时sampleOnClick( )函数被调用。

(4) sampleOnClick( ) 改变变量的值(反转),然后调用sampleRefreshUI( )更换目标窗口的内容显示:当sampleExpanded为true时,显示内容为“-”及子菜单项;当为false时,显示内容为"+"。即一个简单的展开、折叠效果。


2. 构建菜单树

真正的菜单有多个菜单项,每一组都可以独立的展开、折叠,因此,仅一个变量sampleExpanded是不足以保存这么多数据的。应该一个数组,来保存每组菜单的文本和状态信息。再统一的生成一个树状展示。

定义菜单为Menu, 菜单项为MenuItem

function MenuItem(l, h, t)
{
	this.label = l;
	this.href = h;
	this.target = t;	
}

function Menu(lb)
{
	this.itemArray = new Array();
	this.expanded = true;
	this.index = -1;
	this.label = lb;		
	
	this.addItem = function(l, h, t)
	{
		var item = new MenuItem(l,h,t);
		this.itemArray.push(item);
	};				
}
再定义一个MenuTree,来统一的管理各Menu,并负责生成innerHtml

function MenuTree(container)
{
	this.menuArray = new Array();
	this.count = 0;
	this.span = container;
	this.target = null;
	
	// 图标
	this.iconOpen = null;
	this.iconClosed = null;
	
	// 选中的菜单项 
	this.menuSelected = -1;
	this.menuItemSelected = -1;
	
	this.setDefaultTarget = function(target)
	{
	};
	this.setIcon = function(urlOpen, urlClosed)
	{
	};	
	this.addMenu = function(menu)
	{
	};
	this.getMenu = function(index)
	{
	};
	this.expandAll = function(yes)
	{
	};
	this.toHtml = function()
	{		
	};			
}
我把函数实现都给去了,相信大家可以根据这个框架来实现一个全功能的菜单了。注意回调函数sampleOnClick()和界面刷新函数sampleRefreshUI()仍然是必要的,只是sampleOnClick()应该传入一个参数,表示是哪个Menu被点击了。