使用函数递归实现基于php和MySQL的动态树型菜单树型菜单在很多桌面应用系统中都有非常广泛的应用,其主要优点是结构清晰,利于使用者非常清楚的知道目前自己所在的位置。但在web上树型菜单的应用因为没有理想的现成组件可以拿过来直接使用,所以一般的情况下,程序员主要是通过JavaScript来实现一些简单的树型结构菜单,但这些菜单往往都是事先定好各菜单项目,以及各菜单项目之间的层次关系,不利于扩充,一旦需要另一个菜单结构时,往往还需要重新编写,因此使用起来不是很方便。     
    
经过对函数递归的研究,我发现这种树型菜单可以通过递归函数,使树型菜单的显示实现动态变化,并没有级数的限制。下面就是我用php,MySQL,JavaScript写的一个动态树型菜单的处理代码,如果大家有兴趣的话,就和我一起来看看我是如何实现的吧:)     
    
首先,我们需要一个数据库,在这个数据库中,我们建立以下一张表:     
    
CREATE TABLE menu (     
id tinyint(4) NOT NULL auto_increment,     
parent_id tinyint(4) DEFAULT '0' NOT NULL,     
name varchar(20),     
url varchar(60),     
PRIMARY KEY (id)     
);     
    
这张表中     
id 为索引     
parent_id 用来保存上一级菜单的id号,如果是一级菜单则为0     
name 为菜单的名称,也就是要在页面上显示的菜单内容     
url 如果某菜单为末级菜单,则需要指定该连接的url地址,这个字段就是用来保存此地址的,其他非末级菜单,该字段为空     
    
好了,数据库有了,你就可以添加一些记录了,下面是我做测试的时候,使用的一些记录:     
    
INSERT INTO menu VALUES ( '1', '0', '人事管理', '');     
INSERT INTO menu VALUES ( '2', '0', '通讯交流', '');     
INSERT INTO menu VALUES ( '3', '1', '档案管理', '');     
INSERT INTO menu VALUES ( '4', '1', '考勤管理', 'http://localhost/personal/attendance.php');     
INSERT INTO menu VALUES ( '5', '2', '通讯录', '');     
INSERT INTO menu VALUES ( '6', '2', '网络会议', '');     
INSERT INTO menu VALUES ( '7', '3', '新增档案', 'http://localhost/personal/add_achive.php');     
INSERT INTO menu VALUES ( '8', '3', '查询档案', 'http://localhost/personal/search_archive.php');     
INSERT INTO menu VALUES ( '9', '3', '删除档案', 'http://localhost/personal/delete_archive.php');     
INSERT INTO menu VALUES ( '10', '5', '新增通讯记录', 'http://localhost/communication/add_address.php');     
INSERT INTO menu VALUES ( '11', '5', '查询通讯记录', 'http://localhost/communication/search_address.php');     
INSERT INTO menu VALUES ( '12', '5', '删除通讯记录', 'http://localhost/communication/delete_address.php');     
INSERT INTO menu VALUES ( '13', '6', '召开会议', 'http://localhost/communication/convence_meeting.php');     
INSERT INTO menu VALUES ( '14', '6', '会议查询', 'http://localhost/communication/search_meeting.ph');     
    
在添加记录的时候,一定要注意,非一级菜单的parent_id一定要指定为上级菜单的ID号,否则你的菜单是不会显示出来的:)     
    
好了!有了数据库,下面就是通过php,JavaScript把菜单从数据库中读出来,并显示出来了:)     
    
1、JavaScript脚本:     
function ShowMenu(MenuID)     
{     
if(MenuID.style.display=="none")     
{     
MenuID.style.display="";     
}     
else     
{     
MenuID.style.display="none";     
}     
}     
这个脚本很简单,就是用来响应点击某个菜单被点击的事件的。     
    
2、CSS文件:     
<!-- 表格样式 -->     
TD {     
FONT-FAMILY: "Verdana", "宋体"; FONT-SIZE: 12px; LINE-HEIGHT: 130%; letter-spacing:1px     
}     
    
<!-- 超级连接样式 -->     
A:link {     
COLOR: #990000; FONT-FAMILY: "Verdana", "宋体"; FONT-SIZE: 12px; TEXT-DECORATION: none; letter-spacing:1px     
}     
A:visited {     
COLOR: #990000; FONT-FAMILY: "Verdana", "宋体"; FONT-SIZE: 12px; TEXT-DECORATION: none; letter-spacing:1px     
}     
A:active {     
COLOR: #990000; FONT-FAMILY: "Verdana", "宋体"; FONT-SIZE: 12px; TEXT-DECORATION: none; letter-spacing:1px     
}     
A:hover {     
COLOR: #ff0000; FONT-FAMILY: "Verdana", "宋体"; FONT-SIZE: 12px; TEXT-DECORATION: underline; letter-spacing:1px     
}     
    
<!-- 其他样式 -->     
.Menu {     
COLOR:#000000; FONT-FAMILY: "Verdana", "宋体"; FONT-SIZE: 12px; CURSOR: hand     
}     
    
定义了一些基本的样式信息,比如字体,颜色,超级连接的样式等,如果你想改变样式的话,只要修改这里就行了!     
    
3、下面就是我的php页面了!     
    
<html>     
<head>     
<link href='style.css' rel=stylesheet>     
<script language="JavaScript" src="TreeMenu.js"></script>     
</head>     
<body>     
<?php     
//基本变量设置     
$GLOBALS["ID"] =1; //用来跟踪下拉菜单的ID号     
$layer=1; //用来跟踪当前菜单的级数     
    
//连接数据库     
$Con=mysql_connect("localhost","root","");     
mysql_select_db("work");     
    
//提取一级菜单     
$sql="select * from menu where parent_id=0";     
$result=mysql_query($sql,$Con);     
    
//如果一级菜单存在则开始菜单的显示     
if(mysql_num_rows($result)>0) ShowTreeMenu($Con,$result,$layer,$ID);     
    
    
//=============================================     
//显示树型菜单函数 ShowTreeMenu($con,$result,$layer)     
//$con:数据库连接     
//$result:需要显示的菜单记录集     
//layer:需要显示的菜单的级数     
//=============================================     
function ShowTreeMenu($Con,$result,$layer)     
{     
//取得需要显示的菜单的项目数     
$numrows=mysql_num_rows($result);     
    
//开始显示菜单,每个子菜单都用一个表格来表示     
echo "<table cellpadding='0' cellspacing='0' border='0'>";     
    
for($rows=0;$rows<$numrows;$rows++)     
{     
//将当前菜单项目的内容导入数组     
$menu=mysql_fetch_array($result);     
    
//提取菜单项目的子菜单记录集     
$sql="select * from menu where parent_id=$menu[id]";     
$result_sub=mysql_query($sql,$Con);     
    
echo "<tr>";     
//如果该菜单项目有子菜单,则添加JavaScript onClick语句     
if(mysql_num_rows($result_sub)>0)     
{     
echo "<td width='20'><img src='folder.gif' border='0'></td>";     
echo "<td class='Menu' onClick='javascript:ShowMenu(Menu".$GLOBALS["ID"].");'>";     
}     
else     
{     
echo "<td width='20'><img src='file.gif' border='0'></td>";     
echo "<td class='Menu'>";     
}     
//如果该菜单项目没有子菜单,并指定了超级连接地址,则指定为超级连接,     
//否则只显示菜单名称     
if($menu[url]!="")     
echo "<a href='$menu[url]'>$menu[name]</a>";     
else     
echo $menu[name];     
echo "     
</td>     
</tr>     
";     
    
//如果该菜单项目有子菜单,则显示子菜单     
if(mysql_num_rows($result_sub)>0)     
{     
//指定该子菜单的ID和style,以便和onClick语句相对应     
echo "<tr id=Menu".$GLOBALS["ID"]++." style='display:none'>";     
echo "<td width='20'> </td>";     
echo "<td>";     
//将级数加1     
$layer++;     
//递归调用ShowTreeMenu()函数,生成子菜单     
ShowTreeMenu($Con,$result_sub,$layer);     
//子菜单处理完成,返回到递归的上一层,将级数减1     
$layer--;     
echo "</td></tr>";     
}     
//继续显示下一个菜单项目     
}     
echo "</table>";     
}     
?>     
</body>     
</html>     
    
在上面的php页面里面,我定义了一个函数ShowTreeMenu(),通过这个函数的调用,会从数据库中递归的调出每个菜单项目,并显示在页面上了:)     

解决方案 »

  1.   

    可以读出来,
    但是鼠标点击的响应事件没能实现....页面显示:
      
    图标    人事管理
    图标    通讯交流源文件 :<html>
    <head>
    <link href = 'style.css' rel = stylesheet>
    <script language = "JavaScript" src = "TreeMenu.js"></script>
    </head>
    <body>
    <table cellpadding = '0' cellspacing = '0' border = '0'><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu' onClick = 'javascript: ShowMenu(Menu1);'>人事管理</td></tr><tr id = Menu1 style = 'display:none'><td width = '20'> </td><td><table cellpadding = '0' cellspacing = '0' border = '0'><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu' onClick = 'javascript: ShowMenu(Menu2);'>档案管理</td></tr><tr id = Menu2 style = 'display:none'><td width = '20'> </td><td><table cellpadding = '0' cellspacing = '0' border = '0'><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu'><a href = 'http://localhost/personal/add_achive.php'>新增档案</a></td></tr><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu'><a href = 'http://localhost/personal/search_archive.php'>查询档案</a></td></tr><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu'><a href = 'http://localhost/personal/delete_archive.php'>删除档案</a></td></tr></table></td></tr><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu'><a href = 'http://localhost/personal/attendance.php'>考勤管理</a></td></tr></table></td></tr><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu' onClick = 'javascript: ShowMenu(Menu3);'>通讯交流</td></tr><tr id = Menu3 style = 'display:none'><td width = '20'> </td><td><table cellpadding = '0' cellspacing = '0' border = '0'><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu' onClick = 'javascript: ShowMenu(Menu4);'>通讯录</td></tr><tr id = Menu4 style = 'display:none'><td width = '20'> </td><td><table cellpadding = '0' cellspacing = '0' border = '0'><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu'><a href = 'http://localhost/communication/add_address.php'>新增通讯记录</a></td></tr><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu'><a href = 'http://localhost/communication/search_address.php'>查询通讯记录</a></td></tr><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu'><a href = 'http://localhost/communication/delete_address.php'>删除通讯记录</a></td></tr></table></td></tr><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu' onClick = 'javascript: ShowMenu(Menu5);'>网络会议</td></tr><tr id = Menu5 style = 'display:none'><td width = '20'> </td><td><table cellpadding = '0' cellspacing = '0' border = '0'><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu'><a href = 'http://localhost/communication/convence_meeting.php'>召开会议</a></td></tr><tr><td width = '20'> <img src = 'notes.ico' border = '0'></td><td class = 'Menu'><a href = 'http://localhost/communication/search_meeting.ph'>会议查询</a></td></tr></table></td></tr></table></td></tr></table> </body>
    </html>应该会显示的啊,内容都读出来了呀....
    不好意思,我弄不太懂..javascript也只懂得皮毛....
    请继续关注...
      

  2.   

    能不能发给我一个啊,[email protected]
      

  3.   

    TO: ahpo(ahpo)
    把代碼的說明分別存成style.css  , Treemenu.js  ,Treemenu.php
    運行Treemenu.php
    點擊  "人事管理" 或   "通讯交流" 應該可以展開
      

  4.   

    http://www.soulogic.com/Book/
    不错
      

  5.   

    有的..
    我编写的源代码:1.创建的数据库.mysql> use tree
    Database changed
    mysql> show columns from menu;
    +-----------+-------------+------+-----+---------+----------------+
    | Field     | Type        | Null | Key | Default | Extra          |
    +-----------+-------------+------+-----+---------+----------------+
    | id        | tinyint(4)  |      | PRI | NULL    | auto_increment |
    | parent_id | tinyint(4)  |      |     | 0       |                |
    | name      | varchar(20) | YES  |     | NULL    |                |
    | url       | varchar(60) | YES  |     | NULL    |                |
    +-----------+-------------+------+-----+---------+----------------+
    4 rows in set (0.27 sec)mysql>2.style.css<!--表格样式-->
    TD 
    {
    font-family: "Verdana","宋体";font-size: 12pt; line-height: 130%; letter-spacing: 1px;
    }<!--超链接样式-->
    A:link
    {
    color: #990000; font-family: "Verdana", "宋体"; font-size: 12px; text-decoration: none; letter-spacing: 1px
    }
    A:visited
    {
    color: #990000; font-family: "Verdana", "宋体"; font-size: 12px; text-decoration: none; letter-spacing: 1px
    }
    A:active
    {
    color: #990000; font-family: "Verdana", "宋体"; font-size: 12px; text-decoration: none; letter-spacing: 1px
    }
    A:hover
    {
    color: #ff0000; font-family: "Verdana", "宋体"; font-size: 12px; text-decoration: underline; letter-spacing: 1px
    }<!--其它样式-->
    .Menu
    {
    color: #000000; font-family: "Verdana", "宋体"; font-size: 12px; cursor: hand
    }3.TreeMenu.js//响应点击某个菜单被点击的事件;function ShowMenu(MenuID)
    {
    if (MenuID.style.display == "none")
    {
    MenuID.style.display == "";
    }
    else
    {
    MenuID.style.display = "none";
    }
    }4.index.php<html>
    <head>
    <link href = 'style.css' rel = stylesheet>
    <script language = "JavaScript" src = "TreeMenu.js"></script>
    </head>
    <body>
    <?php
    //设置基本变量
    $GLOBALS["ID"] = 1;//用来跟踪下拉菜单的ID号
    $layer = 1;  //用来跟踪当前菜单的级数;

    //connect the dababase;
    $Con = mysql_connect("localhost", "root", "root");
    //==================================
    //数据库的连接
    //if ($Con>0)
    //{
    // echo "数据库连接成功...";
    //}
    //else
    //{
    // echo "数据库连接失败...";
    //}
    //==================================
    mysql_select_db("tree");

    //提取一级菜单;
    $sql = "select * from menu where parent_id = 0";
    $result = mysql_query($sql, $Con);

    //如果一级菜单存在则开始菜单的显示;
    if (mysql_num_rows($result) > 0) ShowTreeMenu($Con, $result, $layer, $ID);

    //===============================================
    //显示出树型菜单函数ShowTreeMenu($Con, $result, $layer)
    //$Con: connect the database
    //$result: 需要显示出的菜单记录集
    //$layer: 需要显示出的菜单的级数;
    //================================================
    function ShowTreeMenu($Con, $result, $layer)
    {
    //get the number of menu which need to be display;
    $numrows = mysql_num_rows($result);

    //begin to display menus, every child menu use a table to express
    echo "<table cellpadding = '0' cellspacing = '0' border = '0'>";

    for($rows = 0; $rows < $numrows; $rows++)
    {
    //put the content of current menu into a array
    $menu = mysql_fetch_array($result);

    //get the child menu of the menu
    $sql = "select * from menu where parent_id = $menu[id]";
    $result_sub = mysql_query($sql, $Con);

    echo "<tr>";
    $success = success;
    $ahpo = ahpo;
    //if该菜单项目有子菜单,则添加JavaScript onClick语句
    if (mysql_num_rows($result_sub) > 0)
    {
    echo "<td width = '20'> <img src = 'notes.ico' border = '0'></td>";
    echo "<td class = 'Menu' onClick = 'javascript: ShowMenu(Menu".$GLOBALS["ID"].");'>";
    }
    else
    {
    echo "<td width = '20'> <img src = 'notes.ico' border = '0'></td>";
    echo "<td class = 'Menu'>";
    }
    //如果该菜单项目没有子菜单,并指定了超级连接的地址,则指定为超级连接
    //否则只显示出菜单名称;
    if ($menu[url] != "")
    echo "<a href = '$menu[url]'>$menu[name]</a>";
    else
    echo $menu[name];
    echo "</td></tr>";

    //如果把该项菜单项目有子菜单,则显示子菜单
    if (mysql_num_rows($result_sub)>0)
    {
    //指定该子菜单的ID和SYTLE,以便和onClick语句相对应
    echo "<tr id = Menu".$GLOBALS["ID"]++." style = 'display:none'>";
    echo "<td width = '20'> </td>";
    echo "<td>";
    //级数加一
    $layer++;
    //递归调用ShowTreeMenu()函数,生成子菜单
    ShowTreeMenu($Con, $result_sub, $layer);
    //子菜单处理完成,返回到递归的上一层,将级数减一
    $layer--;
    echo "</td></tr>";
    }
    //继续现实下一个菜单项目;
    }
    echo "</table>";
    }
    ?>
    </body>
    </html>